list old sessions
This commit is contained in:
+274
-107
@@ -1,5 +1,5 @@
|
|||||||
import { FC, useState, useRef, useEffect } from "react";
|
import { FC, useState, useRef, useEffect } from "react";
|
||||||
import { Send, CloseCircle, User } from "iconsax-react";
|
import { Send, CloseCircle, User, Add, ArrowRight } from "iconsax-react";
|
||||||
import io, { Socket } from "socket.io-client";
|
import io, { Socket } from "socket.io-client";
|
||||||
import { SOCKET_EVENTS } from "./constants";
|
import { SOCKET_EVENTS } from "./constants";
|
||||||
import { useSocketHandlers } from "./hooks/useSocketHandlers";
|
import { useSocketHandlers } from "./hooks/useSocketHandlers";
|
||||||
@@ -7,6 +7,7 @@ import { useMessages } from "./hooks/useMessages";
|
|||||||
import { Message } from "./types";
|
import { Message } from "./types";
|
||||||
import { getToken } from "../config/func";
|
import { getToken } from "../config/func";
|
||||||
import "./chatbot.css"; // Import CSS for animations
|
import "./chatbot.css"; // Import CSS for animations
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
// Helper function to format text with markdown-like syntax
|
// Helper function to format text with markdown-like syntax
|
||||||
export const formatText = (text: string) => {
|
export const formatText = (text: string) => {
|
||||||
@@ -45,6 +46,14 @@ interface ChatbotProps {
|
|||||||
// Connection status types
|
// Connection status types
|
||||||
type ConnectionStatus = "disconnected" | "connecting" | "connected" | "error";
|
type ConnectionStatus = "disconnected" | "connecting" | "connected" | "error";
|
||||||
|
|
||||||
|
// Session type definition
|
||||||
|
interface ChatSession {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
||||||
// State
|
// State
|
||||||
const [inputValue, setInputValue] = useState<string>("");
|
const [inputValue, setInputValue] = useState<string>("");
|
||||||
@@ -55,11 +64,14 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
const [currentSessionId, setCurrentSessionId] = useState<string | null>(null);
|
const [currentSessionId, setCurrentSessionId] = useState<string | null>(null);
|
||||||
const [socket, setSocket] = useState<Socket | null>(null);
|
const [socket, setSocket] = useState<Socket | null>(null);
|
||||||
const [showChatbot, setShowChatbot] = useState<boolean>(false);
|
const [showChatbot, setShowChatbot] = useState<boolean>(false);
|
||||||
// const [showConnectionMessage, setShowConnectionMessage] =
|
|
||||||
// useState<boolean>(false);
|
|
||||||
const [reconnectAttempts, setReconnectAttempts] = useState<number>(0);
|
const [reconnectAttempts, setReconnectAttempts] = useState<number>(0);
|
||||||
const maxReconnectAttempts = 5;
|
const maxReconnectAttempts = 5;
|
||||||
|
|
||||||
|
// Sessions related state
|
||||||
|
const [sessions, setSessions] = useState<ChatSession[]>([]);
|
||||||
|
const [isLoadingSessions, setIsLoadingSessions] = useState<boolean>(false);
|
||||||
|
const [showSessionSelect, setShowSessionSelect] = useState<boolean>(true);
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
const apiBaseUrl = import.meta.env.VITE_BASE_URL;
|
const apiBaseUrl = import.meta.env.VITE_BASE_URL;
|
||||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -73,6 +85,7 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
addMessage,
|
addMessage,
|
||||||
addSystemMessage,
|
addSystemMessage,
|
||||||
updateMessage,
|
updateMessage,
|
||||||
|
setMessages,
|
||||||
} = useMessages();
|
} = useMessages();
|
||||||
const { setupSocketHandlers } = useSocketHandlers({
|
const { setupSocketHandlers } = useSocketHandlers({
|
||||||
socket,
|
socket,
|
||||||
@@ -147,10 +160,11 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
// Connect to socket when component mounts
|
// Connect to socket and fetch sessions when component mounts
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
connectSocket();
|
connectSocket();
|
||||||
|
fetchSessions();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup on unmount or when closed
|
// Cleanup on unmount or when closed
|
||||||
@@ -198,17 +212,190 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
};
|
};
|
||||||
}, [socket]); // Only depend on socket, not setupSocketHandlers
|
}, [socket]); // Only depend on socket, not setupSocketHandlers
|
||||||
|
|
||||||
// Show connection message only briefly when status changes
|
// Fetch user's previous chat sessions
|
||||||
useEffect(() => {
|
const fetchSessions = async () => {
|
||||||
// Always show connection status, don't hide it
|
try {
|
||||||
// setShowConnectionMessage(true);
|
setIsLoadingSessions(true);
|
||||||
|
const token = await getToken();
|
||||||
|
const response = await axios.get(`${apiBaseUrl}/chatbot/sessions`, {
|
||||||
|
headers: { Authorization: `Bearer ${token}` }
|
||||||
|
});
|
||||||
|
|
||||||
return () => {
|
// Extract sessions from response.data.data as the API returns { statusCode, success, data: [...sessions] }
|
||||||
if (connectionTimeoutRef.current) {
|
const sessionsData = response.data?.data || [];
|
||||||
clearTimeout(connectionTimeoutRef.current);
|
setSessions(sessionsData);
|
||||||
|
console.log("📝 Fetched sessions:", sessionsData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching sessions:", error);
|
||||||
|
addSystemMessage("خطا در دریافت جلسات قبلی", "error");
|
||||||
|
} finally {
|
||||||
|
setIsLoadingSessions(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Join an existing chat session
|
||||||
|
const joinChat = (sessionId: string) => {
|
||||||
|
if (!socket || !socket.connected) {
|
||||||
|
addSystemMessage("اتصال Socket.IO برقرار نیست", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get user ID from localStorage or use a default
|
||||||
|
const userId =
|
||||||
|
localStorage.getItem(import.meta.env.VITE_USER_ID_KEY || "user_id") ||
|
||||||
|
localStorage.getItem("userId") ||
|
||||||
|
"anonymous_user";
|
||||||
|
|
||||||
|
console.log(`🔄 Joining chat session: ${sessionId}`);
|
||||||
|
socket.emit(SOCKET_EVENTS.JOIN_CHAT, {
|
||||||
|
sessionId: sessionId,
|
||||||
|
userId: userId,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load a specific session with its messages
|
||||||
|
const loadSession = async (sessionId: string) => {
|
||||||
|
try {
|
||||||
|
setIsProcessing(true);
|
||||||
|
const token = await getToken();
|
||||||
|
|
||||||
|
// First ensure we have a socket connection
|
||||||
|
if (!socket || !socket.connected) {
|
||||||
|
console.log("Socket not connected, connecting first...");
|
||||||
|
await connectSocketPromise(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await axios.get(`${apiBaseUrl}/chatbot/sessions/${sessionId}`, {
|
||||||
|
headers: { Authorization: `Bearer ${token}` }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extract session data from response.data.data
|
||||||
|
const sessionData = response.data?.data || {};
|
||||||
|
|
||||||
|
// Set current session ID
|
||||||
|
setCurrentSessionId(sessionId);
|
||||||
|
|
||||||
|
// Convert API messages to our message format and load them
|
||||||
|
if (sessionData && sessionData.messages) {
|
||||||
|
const formattedMessages = sessionData.messages.map((msg: any) => ({
|
||||||
|
id: msg.id || Date.now().toString() + Math.random().toString(),
|
||||||
|
text: msg.content || msg.text || "",
|
||||||
|
isUser: msg.type === "user",
|
||||||
|
isSystem: msg.type === "system",
|
||||||
|
timestamp: new Date(msg.createdAt || msg.timestamp || Date.now()),
|
||||||
|
metadata: msg.metadata || {}
|
||||||
|
}));
|
||||||
|
|
||||||
|
setMessages(formattedMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join the chat session
|
||||||
|
if (socket && socket.connected) {
|
||||||
|
joinChat(sessionId);
|
||||||
|
} else {
|
||||||
|
console.error("Still couldn't connect socket after retrying");
|
||||||
|
addSystemMessage("خطا در اتصال به سرور چت", "error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to chat view
|
||||||
|
setShowSessionSelect(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error loading session:", error);
|
||||||
|
addSystemMessage("خطا در بارگذاری جلسه", "error");
|
||||||
|
} finally {
|
||||||
|
setIsProcessing(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Promise-based socket connection
|
||||||
|
const connectSocketPromise = (token: string | undefined): Promise<Socket> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
setConnectionStatus("connecting");
|
||||||
|
|
||||||
|
if (!apiBaseUrl) {
|
||||||
|
console.error("API base URL not defined");
|
||||||
|
setConnectionStatus("error");
|
||||||
|
reject(new Error("API base URL not defined"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
console.error("No authentication token available");
|
||||||
|
setConnectionStatus("error");
|
||||||
|
reject(new Error("No authentication token available"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("🔄 Connecting to Socket.IO...");
|
||||||
|
const newSocket = io(`${apiBaseUrl}/chat`, {
|
||||||
|
auth: { token }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up connection timeout
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
if (newSocket.connected) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("❌ Connection timeout");
|
||||||
|
setConnectionStatus("error");
|
||||||
|
reject(new Error("Connection timeout"));
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
// Handle successful connection
|
||||||
|
newSocket.on("connect", () => {
|
||||||
|
console.log("✅ Socket connected successfully");
|
||||||
|
setConnectionStatus("connected");
|
||||||
|
setSocket(newSocket);
|
||||||
|
clearTimeout(timeout);
|
||||||
|
resolve(newSocket);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle connection error
|
||||||
|
newSocket.on("connect_error", (err) => {
|
||||||
|
console.error("Socket connection error:", err);
|
||||||
|
setConnectionStatus("error");
|
||||||
|
clearTimeout(timeout);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Socket connection promise error:", error);
|
||||||
|
setConnectionStatus("error");
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a new chat session
|
||||||
|
const handleCreateNewSession = async () => {
|
||||||
|
try {
|
||||||
|
setIsProcessing(true);
|
||||||
|
setShowSessionSelect(false);
|
||||||
|
setCurrentSessionId(null);
|
||||||
|
setMessages([]);
|
||||||
|
|
||||||
|
// Ensure socket is connected
|
||||||
|
if (!socket || !socket.connected) {
|
||||||
|
const token = await getToken();
|
||||||
|
await connectSocketPromise(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new session
|
||||||
|
if (socket && socket.connected) {
|
||||||
|
createSession(socket);
|
||||||
|
} else {
|
||||||
|
console.error("Failed to connect socket for new session");
|
||||||
|
addSystemMessage("خطا در اتصال به سرور چت", "error");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating new session:", error);
|
||||||
|
addSystemMessage("خطا در ایجاد جلسه جدید", "error");
|
||||||
|
} finally {
|
||||||
|
setIsProcessing(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [connectionStatus]);
|
|
||||||
|
|
||||||
const scrollToBottom = () => {
|
const scrollToBottom = () => {
|
||||||
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||||
@@ -216,41 +403,9 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
|
|
||||||
const connectSocket = async () => {
|
const connectSocket = async () => {
|
||||||
try {
|
try {
|
||||||
setConnectionStatus("connecting");
|
|
||||||
|
|
||||||
// Get token from environment or localStorage
|
|
||||||
const token = await getToken();
|
const token = await getToken();
|
||||||
|
await connectSocketPromise(token);
|
||||||
if (!apiBaseUrl) {
|
|
||||||
console.error("API base URL not defined in environment variables");
|
|
||||||
setConnectionStatus("error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("🔄 Connecting to Socket.IO...");
|
|
||||||
const newSocket = io(`${apiBaseUrl}/chat`, {
|
|
||||||
auth: {
|
|
||||||
token: token,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
setSocket(newSocket);
|
|
||||||
setReconnectAttempts(0);
|
setReconnectAttempts(0);
|
||||||
|
|
||||||
// Set a timeout for connection
|
|
||||||
connectionTimeoutRef.current = setTimeout(() => {
|
|
||||||
if (connectionStatus === "connecting") {
|
|
||||||
console.log("❌ Connection timeout");
|
|
||||||
setConnectionStatus("error");
|
|
||||||
}
|
|
||||||
}, 10000);
|
|
||||||
|
|
||||||
// Create session after connection - like in JS version
|
|
||||||
setTimeout(() => {
|
|
||||||
if (newSocket.connected) {
|
|
||||||
createSession(newSocket);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Socket connection error:", error);
|
console.error("Socket connection error:", error);
|
||||||
setConnectionStatus("error");
|
setConnectionStatus("error");
|
||||||
@@ -297,29 +452,10 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
|
|
||||||
console.log("🔄 Creating new session via Socket.IO...");
|
console.log("🔄 Creating new session via Socket.IO...");
|
||||||
socketInstance.emit(SOCKET_EVENTS.CREATE_SESSION, {
|
socketInstance.emit(SOCKET_EVENTS.CREATE_SESSION, {
|
||||||
title: `جلسه ${new Date().toLocaleDateString("fa-IR")}`,
|
title: `چت ${new Date().toLocaleDateString("fa-IR")}`,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// const joinChat = (sessionId: string) => {
|
|
||||||
// if (!socket || !socket.connected) {
|
|
||||||
// addSystemMessage("اتصال Socket.IO برقرار نیست", "error");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Get user ID from localStorage or use a default
|
|
||||||
// const userId =
|
|
||||||
// localStorage.getItem(import.meta.env.VITE_USER_ID_KEY || "user_id") ||
|
|
||||||
// localStorage.getItem("userId") ||
|
|
||||||
// "anonymous_user";
|
|
||||||
|
|
||||||
// console.log(`🔄 Joining chat session: ${sessionId}`);
|
|
||||||
// socket.emit(SOCKET_EVENTS.JOIN_CHAT, {
|
|
||||||
// sessionId: sessionId,
|
|
||||||
// userId: userId,
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
const handleSendMessage = () => {
|
const handleSendMessage = () => {
|
||||||
const message = inputValue.trim();
|
const message = inputValue.trim();
|
||||||
|
|
||||||
@@ -422,40 +558,23 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get connection status icon and text
|
// Format date for session list
|
||||||
// const getConnectionStatusInfo = () => {
|
const formatDate = (dateString: string) => {
|
||||||
// switch (connectionStatus) {
|
const date = new Date(dateString);
|
||||||
// case "connected":
|
return date.toLocaleDateString("fa-IR", {
|
||||||
// return {
|
year: "numeric",
|
||||||
// icon: <Wifi size={16} className="text-green-400" />,
|
month: "long",
|
||||||
// text: "متصل",
|
day: "numeric",
|
||||||
// className: "bg-green-100 text-green-800",
|
});
|
||||||
// };
|
};
|
||||||
// case "connecting":
|
|
||||||
// return {
|
// Handle return to sessions list
|
||||||
// icon: <Wifi size={16} className="text-yellow-400 animate-pulse" />,
|
const handleReturnToSessions = () => {
|
||||||
// text: "در حال اتصال...",
|
setShowSessionSelect(true);
|
||||||
// className: "bg-yellow-100 text-yellow-800",
|
};
|
||||||
// };
|
|
||||||
// case "error":
|
|
||||||
// return {
|
|
||||||
// icon: <Wifi size={16} className="text-red-500" />,
|
|
||||||
// text: "خطا در اتصال",
|
|
||||||
// className: "bg-red-100 text-red-800",
|
|
||||||
// };
|
|
||||||
// default:
|
|
||||||
// return {
|
|
||||||
// icon: <Wifi size={16} variant="Bold" className="text-gray-500" />,
|
|
||||||
// text: "قطع اتصال",
|
|
||||||
// className: "bg-gray-100 text-gray-800",
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
// const connectionInfo = getConnectionStatusInfo();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`fixed bottom-20 right-4 w-80 sm:w-96 bg-white rounded-xl shadow-xl flex flex-col z-50 border border-gray-200 transition-all duration-300 ease-in-out ${showChatbot
|
className={`fixed bottom-20 right-4 w-80 sm:w-96 bg-white rounded-xl shadow-xl flex flex-col z-50 border border-gray-200 transition-all duration-300 ease-in-out ${showChatbot
|
||||||
@@ -475,18 +594,16 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
: "bg-red-400"
|
: "bg-red-400"
|
||||||
}`}
|
}`}
|
||||||
></div>
|
></div>
|
||||||
<h3 className="font-bold text-base">چت بات داناک</h3>
|
{!showSessionSelect && (
|
||||||
{/* Always show a compact connection status */}
|
<button
|
||||||
{/* <div
|
onClick={handleReturnToSessions}
|
||||||
className={`flex items-center text-xs mr-2 ml-2 ${connectionStatus === "connected"
|
className="ml-2 p-1 focus:outline-none hover:bg-gray-700 rounded-full transition-colors"
|
||||||
? "text-green-200"
|
title="برگشت به لیست جلسات"
|
||||||
: connectionStatus === "connecting"
|
|
||||||
? "text-yellow-200"
|
|
||||||
: "text-red-200"
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{connectionInfo.icon}
|
<ArrowRight size={18} />
|
||||||
</div> */}
|
</button>
|
||||||
|
)}
|
||||||
|
<h3 className="font-bold text-base">چت بات داناک</h3>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
@@ -497,6 +614,54 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{showSessionSelect ? (
|
||||||
|
/* Sessions Selection Screen */
|
||||||
|
<div className="flex-1 p-3.5 overflow-y-auto bg-gray-50">
|
||||||
|
<div className="mb-4">
|
||||||
|
<h3 className="text-lg font-bold text-gray-800 mb-2">جلسات قبلی شما</h3>
|
||||||
|
<p className="text-sm text-gray-600">یک جلسه را انتخاب کنید یا جلسه جدیدی بسازید.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoadingSessions ? (
|
||||||
|
<div className="flex justify-center items-center h-64">
|
||||||
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"></div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
onClick={handleCreateNewSession}
|
||||||
|
className="w-full bg-black text-white rounded-lg p-3 mb-4 flex items-center justify-center hover:bg-gray-800 transition-colors"
|
||||||
|
>
|
||||||
|
<Add size={20} className="ml-2" />
|
||||||
|
<span>شروع جلسه جدید</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{sessions.length === 0 ? (
|
||||||
|
<div className="text-center text-gray-500 p-4">
|
||||||
|
هنوز هیچ جلسهای ندارید
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="space-y-2">
|
||||||
|
{sessions.map((session) => (
|
||||||
|
<div
|
||||||
|
key={session.id}
|
||||||
|
onClick={() => loadSession(session.id)}
|
||||||
|
className="bg-white p-3 rounded-lg shadow-sm cursor-pointer hover:bg-gray-100 transition-colors"
|
||||||
|
>
|
||||||
|
<div className="font-medium">{session.title}</div>
|
||||||
|
<div className="text-xs text-gray-500 mt-1">
|
||||||
|
{formatDate(session.createdAt)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
/* Chat UI */
|
||||||
|
<>
|
||||||
{/* Messages */}
|
{/* Messages */}
|
||||||
<div
|
<div
|
||||||
className="flex-1 p-3.5 overflow-y-auto bg-gray-50"
|
className="flex-1 p-3.5 overflow-y-auto bg-gray-50"
|
||||||
@@ -636,6 +801,8 @@ const Chatbot: FC<ChatbotProps> = ({ isOpen, onClose }) => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,5 +81,6 @@ export const useMessages = () => {
|
|||||||
updateMessage,
|
updateMessage,
|
||||||
removeMessage,
|
removeMessage,
|
||||||
clearMessages,
|
clearMessages,
|
||||||
|
setMessages,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user