import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate, useParams } from 'react-router-dom'; import ConversationMessages from './ConversationMessages'; import MessageInput from '../components/MessageInput'; import conversationService from '../api/services/conversationService'; import { selectClientAPIKey, setClientApiKey, updateQuery, addQuery, fetchSharedAnswer, selectStatus, } from './sharedConversationSlice'; import { setIdentifier, setFetchedData } from './sharedConversationSlice'; import { useDispatch } from 'react-redux'; import { AppDispatch } from '../store'; import { selectDate, selectTitle, selectQueries, } from './sharedConversationSlice'; import { useSelector } from 'react-redux'; import { Helmet } from 'react-helmet'; import { formatDate } from '../utils/dateTimeUtils'; export const SharedConversation = () => { const navigate = useNavigate(); const { identifier } = useParams(); //identifier is a uuid, not conversationId const queries = useSelector(selectQueries); const title = useSelector(selectTitle); const date = useSelector(selectDate); const apiKey = useSelector(selectClientAPIKey); const status = useSelector(selectStatus); const [input, setInput] = useState(''); const { t } = useTranslation(); const dispatch = useDispatch(); const [lastQueryReturnedErr, setLastQueryReturnedErr] = useState(false); useEffect(() => { identifier && dispatch(setIdentifier(identifier)); }, []); useEffect(() => { if (queries.length) { queries[queries.length - 1].error && setLastQueryReturnedErr(true); queries[queries.length - 1].response && setLastQueryReturnedErr(false); //considering a query that initially returned error can later include a response property on retry } }, [queries[queries.length - 1]]); const fetchQueries = () => { identifier && conversationService .getSharedConversation(identifier || '') .then((res) => { if (res.status === 404 || res.status === 400) navigate('/pagenotfound'); return res.json(); }) .then((data) => { if (data.success) { dispatch( setFetchedData({ queries: data.queries, title: data.title, date: formatDate(data.timestamp), identifier, }), ); data.api_key && dispatch(setClientApiKey(data.api_key)); } }); }; const handleQuestionSubmission = () => { if (input && status !== 'loading') { if (lastQueryReturnedErr) { // update last failed query with new prompt dispatch( updateQuery({ index: queries.length - 1, query: { prompt: input, }, }), ); handleQuestion({ question: queries[queries.length - 1].prompt, isRetry: true, }); } else { handleQuestion({ question: input }); } setInput(''); } }; const handleQuestion = ({ question, isRetry = false, }: { question: string; isRetry?: boolean; }) => { question = question.trim(); if (question === '') return; !isRetry && dispatch(addQuery({ prompt: question })); //dispatch only new queries dispatch(fetchSharedAnswer({ question })); }; useEffect(() => { fetchQueries(); }, []); return ( <> {`DocsGPT | ${title}`}

{title}

{t('sharedConv.subtitle')}{' '} DocsGPT

{date}

{apiKey ? ( setInput(e.target.value)} onSubmit={() => handleQuestionSubmission()} loading={status === 'loading'} /> ) : ( )}

{t('sharedConv.meta')}

); };