import { useState } from 'react'; import axios from 'axios'; /** * Custom hook for managing chat-related state and functionality. * It handles input text, chat history, loading state, history navigation, and form submission. * * returns {object} An object containing the state and functions related to chat handling. */ export default function useChatHandler() { // State variables const [inputText, setInputText] = useState(''); const initialChatHistory = localStorage.getItem('chatHistory'); const [chatHistory, setChatHistory] = useState( initialChatHistory ? JSON.parse(initialChatHistory) : [] ); const [loading, setLoading] = useState(false); const [historyIndex, setHistoryIndex] = useState(-1); const [isHistoryNavigation, setIsHistoryNavigation] = useState(false); // Function to handle form submission const handleSubmit = async (text) => { setLoading(true); let success = false; try { const sendTextResponse = await axios.post('http://127.0.0.1:5000/sendText', { text }); const sendQuestionsResponse = await axios.post('http://127.0.0.1:5000/sendQuestions', { text }); const newChatItem = { question: text, response: sendTextResponse.data.output, followUps: sendQuestionsResponse.data.output.followUps.map(followUp => ({ text: followUp, response: null, loading: false })), }; setChatHistory((oldChatHistory) => { const newChatHistory = [...oldChatHistory, newChatItem]; localStorage.setItem('chatHistory', JSON.stringify(newChatHistory)); return newChatHistory; }); setInputText(''); success = true; } catch (error) { console.error(error); } setLoading(false); return success; }; // Function to handle follow-up questions const handleFollowUp = async (chatItemIndex, followUpIndex) => { // set loading to true chatHistory[chatItemIndex].followUps[followUpIndex].loading = true; setChatHistory([...chatHistory]); try { const response = await axios.post('http://127.0.0.1:5000/sendText', { text: chatHistory[chatItemIndex].followUps[followUpIndex].text }); // Update the response and loading state chatHistory[chatItemIndex].followUps[followUpIndex].response = response.data.output; chatHistory[chatItemIndex].followUps[followUpIndex].loading = false; // Get new follow-up questions based on the follow-up response. const sendQuestionsResponse = await axios.post('http://127.0.0.1:5000/sendQuestions', { text: response.data.output }); // Add to FollowUp array const newFollowUps = sendQuestionsResponse.data.output.followUps.map(followUp => ({ text: followUp, response: null, loading: false })); // Insert new follow ups after the current one chatHistory[chatItemIndex].followUps.splice(followUpIndex + 1, 0, ...newFollowUps); setChatHistory([...chatHistory]); } catch (error) { console.error(error); // handle error // set loading to false chatHistory[chatItemIndex].followUps[followUpIndex].loading = false; setChatHistory([...chatHistory]); } }; // Function to handle special keys (Command+Enter, Up Arrow, Down Arrow) const handleKeyDown = (e, handleFormSubmit) => { // If command+enter, submit form if (e.metaKey && e.keyCode === 13) { e.preventDefault(); handleFormSubmit(e); } // If up arrow, navigate one step up in chat history else if (e.keyCode === 38) { e.preventDefault(); if (chatHistory.length > 0) { setIsHistoryNavigation(true); setHistoryIndex((prevHistoryIndex) => { let newHistoryIndex = Math.min(prevHistoryIndex + 1, chatHistory.length - 1); setInputText(chatHistory[chatHistory.length - newHistoryIndex - 1].question); return newHistoryIndex; }); } } // If down arrow, navigate one step down in chat history else if (e.keyCode === 40) { e.preventDefault(); if (chatHistory.length > 0 && historyIndex !== -1) { setIsHistoryNavigation(true); setHistoryIndex((prevHistoryIndex) => { let newHistoryIndex = Math.max(prevHistoryIndex - 1, -1); if (newHistoryIndex === -1) setInputText(''); else setInputText(chatHistory[chatHistory.length - newHistoryIndex - 1].question); return newHistoryIndex; }); } } }; // Function to clear chat history const clearChatHistory = () => { setChatHistory([]); localStorage.removeItem('chatHistory'); }; // Function to handle input text change const handleInputChange = (e) => { setInputText(e.target.value); setIsHistoryNavigation(false); }; // Return the state and functions related to chat handling return { inputText, handleInputChange, setInputText, chatHistory, setChatHistory, loading, handleSubmit, handleKeyDown, clearChatHistory, handleFollowUp, }; }