-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
285 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
"use client"; | ||
|
||
import { useState, useEffect } from 'react'; | ||
import { api } from '@/domain/api/api'; | ||
import Sidebar from '../../components/Sidebar'; | ||
import MessageList from '../../components/MessageList'; | ||
import { useConfig } from '@/domain/config/ConfigProvider'; | ||
import { Button } from "@/components/ui/button" | ||
import { useRouter } from 'next/navigation'; | ||
|
||
// Тип для хранения информации о чате | ||
type Conversation = { | ||
id: number; | ||
name: string; | ||
messages: Array<{ id: number; text: string; sender: string }>; | ||
}; | ||
|
||
// Основная функция компонента | ||
export default function ConversationPage({ params }: { params: { id: string } }) { | ||
// Состояния для хранения списка чатов, текущего чата и сообщений | ||
const [conversations, setConversations] = useState<Conversation[]>([]); | ||
const [currentConversationId, setCurrentConversationId] = useState<number | null>(null); | ||
const [message, setMessage] = useState(''); | ||
const [messages, setMessages] = useState<Array<{ id: number; text: string; sender: string }>>([]); | ||
const [isSidebarOpen, setIsSidebarOpen] = useState(false); | ||
|
||
const config = useConfig(); | ||
const router = useRouter(); | ||
|
||
// Инициализация пользователя | ||
useEffect(() => { | ||
const initializeUser = async () => { | ||
try { | ||
const response = await api.get_messages__user_id_(config.ENDPOINT); | ||
console.log('API response:', response); | ||
|
||
if (response.data && Array.isArray(response.data) && response.data.length > 0) { | ||
const formattedConversations = response.data.map((id: number, index: number) => ({ | ||
id: id, | ||
name: `Чат ${index + 1}`, | ||
messages: [] | ||
})); | ||
|
||
setConversations(formattedConversations); | ||
|
||
const initialConversationId = parseInt(params.id); | ||
setCurrentConversationId(initialConversationId); | ||
|
||
await loadMessagesForConversation(initialConversationId); | ||
} else { | ||
const newConversation = await handleAddConversation(); | ||
setConversations([newConversation]); | ||
setCurrentConversationId(newConversation.id); | ||
router.push(`/conversations/${newConversation.id}`); | ||
} | ||
} catch (error) { | ||
console.error('Ошибка при инициализации пользователя:', error); | ||
} | ||
}; | ||
|
||
initializeUser(); | ||
}, [params.id, config.ENDPOINT, router]); | ||
|
||
useEffect(() => { | ||
const loadData = async () => { | ||
if (currentConversationId) { | ||
await loadMessagesForConversation(currentConversationId); | ||
} | ||
}; | ||
|
||
loadData(); | ||
}, [currentConversationId, config.ENDPOINT]); | ||
|
||
const handleSendMessage = async () => { | ||
if (!message.trim()) return; | ||
|
||
try { | ||
if (currentConversationId === null) { | ||
const newConversation = await handleAddConversation(); | ||
if (!newConversation) { | ||
throw new Error('Не удалось создать новый чат'); | ||
} | ||
} | ||
const newMessage = { | ||
id: messages.length + 1, | ||
text: message, | ||
sender: 'user' | ||
}; | ||
|
||
const conversationIdAtSend = currentConversationId; | ||
|
||
setMessages(prevMessages => [...prevMessages, newMessage]); | ||
setConversations(prevConversations => | ||
prevConversations.map(conversation => | ||
conversation.id === conversationIdAtSend | ||
? { ...conversation, messages: [...conversation.messages, newMessage] } | ||
: conversation | ||
) | ||
); | ||
|
||
const response = await api.sendMessage(config.ENDPOINT, conversationIdAtSend!, message); | ||
|
||
if (!response.task_id) { | ||
throw new Error('Ошибка при отправке сообщения'); | ||
} | ||
|
||
console.log('Сообщение успешно отправлено, task_id:', response.task_id); | ||
setMessage(''); | ||
|
||
let botResponse; | ||
do { | ||
await new Promise(resolve => setTimeout(resolve, 1000)); | ||
botResponse = await api.checkTaskResult(config.ENDPOINT, response.task_id); | ||
} while (!botResponse.ready); | ||
|
||
if (botResponse.successful && botResponse.value) { | ||
const botMessage = { | ||
id: messages.length + 2, | ||
text: botResponse.value.answer, | ||
sender: 'bot' | ||
}; | ||
|
||
setMessages(prevMessages => [...prevMessages, botMessage]); | ||
setConversations(prevConversations => | ||
prevConversations.map(conversation => | ||
conversation.id === currentConversationId | ||
? { ...conversation, messages: [...conversation.messages, botMessage] } | ||
: conversation | ||
) | ||
); | ||
} | ||
|
||
} catch (error) { | ||
console.error('Произошла ошибка:', error); | ||
setMessage(''); | ||
} | ||
}; | ||
|
||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { | ||
if (e.key === 'Enter') { | ||
handleSendMessage(); | ||
} | ||
}; | ||
|
||
const handleChatChange = async (id: number) => { | ||
setCurrentConversationId(id); | ||
await loadMessagesForConversation(id); | ||
router.push(`/conversations/${id}`); | ||
}; | ||
|
||
const handleAddConversation = async () => { | ||
try { | ||
const response = await api.createConversation(config.ENDPOINT); | ||
if (response.conversation_id) { | ||
const maxChatNumber = Math.max(...conversations.map(conv => { | ||
const match = conv.name.match(/Чат (\d+)/); | ||
return match ? parseInt(match[1]) : 0; | ||
}), 0); | ||
|
||
const newChatNumber = maxChatNumber + 1; | ||
|
||
const newConversation = { | ||
id: response.conversation_id, | ||
name: `Чат ${newChatNumber}`, | ||
messages: [] | ||
}; | ||
|
||
setConversations(prevConversations => [...prevConversations, newConversation]); | ||
setCurrentConversationId(newConversation.id); | ||
setMessages([]); | ||
return newConversation; | ||
} else { | ||
throw new Error('Не удалось создать новый чат'); | ||
} | ||
} catch (error) { | ||
console.error('Ошибка при создании чата:', error); | ||
throw error; | ||
} | ||
}; | ||
|
||
const handleDeleteConversation = async (conversationId: number) => { | ||
try { | ||
await api.deleteConversation(config.ENDPOINT, conversationId); | ||
|
||
setConversations(prevConversations => { | ||
const updatedConversations = prevConversations.filter(conversation => conversation.id !== conversationId); | ||
if (updatedConversations.length === 0) { | ||
setCurrentConversationId(null); | ||
setMessages([]); | ||
} else if (currentConversationId === conversationId) { | ||
const newCurrentConversation = updatedConversations[0]; | ||
setCurrentConversationId(newCurrentConversation.id); | ||
setMessages(newCurrentConversation.messages); | ||
} | ||
return updatedConversations; | ||
}); | ||
console.log('Чат успешно удален'); | ||
} catch (error) { | ||
console.error('Ошибка при удалении чата:', error); | ||
} | ||
}; | ||
|
||
const loadMessagesForConversation = async (conversationId: number) => { | ||
try { | ||
const response = await api.getMessages(config.ENDPOINT, conversationId); | ||
if (response && response.length > 0 && response[0].messages && response[0].messages.length > 0) { | ||
const conversationMessages = response[0].messages[0][conversationId]; | ||
if (conversationMessages && Array.isArray(conversationMessages)) { | ||
const formattedMessages = conversationMessages.map((msg: any) => ({ | ||
id: msg.id, | ||
text: msg.text, | ||
sender: msg.role === 1 ? 'bot' : 'user' | ||
})); | ||
setMessages(formattedMessages); | ||
setConversations(prevConversations => | ||
prevConversations.map(conv => | ||
conv.id === conversationId ? { ...conv, messages: formattedMessages } : conv | ||
) | ||
); | ||
} else { | ||
setMessages([]); | ||
} | ||
} else { | ||
setMessages([]); | ||
} | ||
} catch (error) { | ||
console.error('Ошибка при загрузке сообщений:', error); | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="min-h-screen relative overflow-hidden hide-scrollbar"> | ||
<header className="md:hidden fixed top-0 left-0 right-0 z-50 bg-[#17153B] p-4 flex justify-between items-center"> | ||
{isSidebarOpen && ( | ||
<button | ||
onClick={() => setIsSidebarOpen(!isSidebarOpen)} | ||
className="text-white focus:outline-none" | ||
> | ||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" /> | ||
</svg> | ||
</button> | ||
)} | ||
</header> | ||
|
||
<main className="flex h-screen pt-16 md:pt-0"> | ||
<div className="fixed left-0 top-0 h-full md:relative"> | ||
<Sidebar | ||
conversations={conversations} | ||
currentConversationId={currentConversationId} | ||
onConversationChange={handleChatChange} | ||
onAddConversation={handleAddConversation} | ||
onDeleteConversation={(id) => handleDeleteConversation(id)} | ||
isSidebarOpen={isSidebarOpen} | ||
onCloseSidebar={() => setIsSidebarOpen(false)} | ||
/> | ||
</div> | ||
|
||
<div className="flex-1 flex flex-col h-screen ml-[300px] md:ml-0"> | ||
<MessageList messages={messages} /> | ||
|
||
<div className="p-4 bg-white"> | ||
<div className="flex items-stretch"> | ||
<input | ||
type="text" | ||
value={message} | ||
onChange={(e) => setMessage(e.target.value)} | ||
onKeyDown={handleKeyDown} | ||
placeholder="Введите ваш вопрос" | ||
className="flex-grow p-2 bg-[#EFF0F3] border border-gray-300 rounded-l-2xl focus:outline-none h-full" | ||
style={{ color: 'black' }} | ||
/> | ||
<Button | ||
onClick={handleSendMessage} | ||
className="rounded-r-2xl rounded-l-none bg-[#1D1F27] focus:outline-none cursor-pointer hover:bg-[#606371] border-l-0 h-full" | ||
> | ||
Отправить | ||
</Button> | ||
</div> | ||
</div> | ||
</div> | ||
</main> | ||
</div> | ||
); | ||
} |