add experimental chat

This commit is contained in:
Pritimay Sarkar
2024-01-26 23:02:43 +05:30
parent b69791c246
commit 3e4f08b90e
6 changed files with 2020 additions and 44 deletions

1791
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,6 +24,7 @@
"react-dropdown": "^1.11.0", "react-dropdown": "^1.11.0",
"react-flip-numbers": "^3.0.8", "react-flip-numbers": "^3.0.8",
"react-icons": "^4.10.1", "react-icons": "^4.10.1",
"react-markdown": "^9.0.1",
"react-redux": "^8.1.2", "react-redux": "^8.1.2",
"react-router-dom": "^6.14.2", "react-router-dom": "^6.14.2",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",

42
src/components/Gemini.css Normal file
View File

@@ -0,0 +1,42 @@
.user-chat-input {
margin: 10px;
}
.user-message {
background-color: #aaffaa;
padding: 5px;
margin: 5px;
border-radius: 5px;
}
.other-message {
background-color: #aaaaff;
padding: 5px;
margin: 5px;
border-radius: 5px;
}
.typing-animation {
overflow: hidden; /* Hide overflowing text */
border-right: 0.1em solid #000; /* Add a border to simulate the cursor */
white-space: nowrap; /* Ensure the text stays in one line */
animation: typing 1s steps(40, end), blink-caret 0.5s step-end infinite; /* Typing animation */
}
@keyframes typing {
from {
width: 0;
}
to {
width: 100%;
}
}
@keyframes blink-caret {
from, to {
border-color: transparent; /* Blinking cursor effect */
}
50% {
border-color: #000;
}
}

155
src/components/Gemini.js Normal file
View File

@@ -0,0 +1,155 @@
import React, { useState, useEffect, useRef } from 'react';
import { query, collection, onSnapshot, addDoc, where, getDocs, orderBy } from 'firebase/firestore';
import ReactMarkdown from 'react-markdown';
import './Gemini.css'; // Make sure to have your CSS styles for the typewriter effect
import db from '../firebase';
function Gemini() {
const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState('');
const [isTyping, setIsTyping] = useState(false);
const scrollRef = useRef(null);
useEffect(() => {
const loadChatHistory = async () => {
const uid = 'uid'; // Replace with your user ID
const discussionId = 'discussionId'; // Replace with your discussion ID
const collectionPath = `users/${uid}/discussions/${discussionId}/messages`;
const q = query(collection(db, collectionPath), orderBy('createTime'));
try {
const querySnapshot = await getDocs(q);
const loadedMessages = [];
querySnapshot.forEach((doc) => {
const data = doc.data();
loadedMessages.push({ text: data.prompt, sender: 'user' });
if (data.response) {
// Simulate delay for typewriter effect
setTimeout(() => {
// Update the state with the Gemini's response
setMessages((prevMessages) => [
...prevMessages,
{ text: data.response, sender: 'gemini' },
]);
if (scrollRef.current) {
// alert(scrollRef.current.scrollHeight)
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
}
}, 1000); // You can adjust the delay as needed
}
});
// Sort the messages by createTime before updating the state
// loadedMessages.sort((a, b) => a.createTime - b.createTime);
setMessages(loadedMessages);
// Scroll to the bottom
if (scrollRef.current) {
// alert(scrollRef.current.scrollHeight)
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
}
} catch (error) {
console.error('Error loading chat history:', error);
}
};
loadChatHistory();
}, []); // Empty dependency array ensures the effect runs only once on component mount
const handleSendMessage = async () => {
if (newMessage.trim() === '') return;
const uid = 'uid'; // Replace with your user ID
const discussionId = 'discussionId'; // Replace with your discussion ID
const collectionPath = `users/${uid}/discussions/${discussionId}/messages`;
const collectionRef = collection(db, collectionPath);
// Add user's message to the local state first
setMessages([...messages, { text: newMessage, sender: 'user' }]);
setNewMessage('');
// Then, add the user's message to the Firestore collection
// Your existing code for adding user's message remains unchanged
const docRef = await addDoc(collectionRef, {
prompt: newMessage,
});
// Listen for changes in the Firestore document
const unsub = onSnapshot(docRef, (doc) => {
const data = doc.data();
if (data && data.response) {
// Start typewriter animation
// setIsTyping(true);
// Simulate delay for typewriter effect
setTimeout(() => {
// Update the state with the Gemini's response
setMessages((prevMessages) => [...prevMessages, { text: data.response, sender: 'gemini' }]);
// Stop typewriter animation
// setIsTyping(false);
// Scroll to the bottom
if (scrollRef.current) {
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
}
}, 1000); // You can adjust the delay as needed
}
});
if (scrollRef.current) {
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
}
};
return (
<div>
<div style={{ height: '500px', overflowY: 'scroll', border: '1px solid #ccc' }} ref={scrollRef}>
{messages.map((message, index) => (
<div key={index} className={message.sender === 'user' ? 'user-message' : 'other-message'}>
{message.sender === 'gemini' && isTyping ? (
// Display typing animation for Gemini's response
<div className="typing-animation">Gemini is typing...</div>
) : (
// Display the actual message
<ReactMarkdown>{message.text}</ReactMarkdown>
)}
</div>
))}
</div>
<div className="user-chat-input">
<input
type="text"
value={newMessage}
onChange={(e) => setNewMessage(e.target.value)}
placeholder="Type your message..."
style={{ marginRight: '8px', padding: '8px', fontSize: '16px', width: '50vw' }}
/>
<button
onClick={handleSendMessage}
style={{
backgroundColor: '#4CAF50',
color: 'white',
padding: '10px 20px',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '16px',
}}
>
Send
</button>
</div>
</div>
);
}
export default Gemini;

View File

@@ -3,30 +3,7 @@ import { getFirestore} from "firebase/firestore";
import { initializeApp } from "firebase/app"; import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics"; import { getAnalytics } from "firebase/analytics";
// /* dev and test */ /* dev and test */
// const firebaseConfig = {
// apiKey: "AIzaSyBFl_YkJ5PMIvMY3G70313SyrqemjFnUv8",
// authDomain: "hpos-af3cc.firebaseapp.com",
// projectId: "hpos-af3cc",
// storageBucket: "hpos-af3cc.appspot.com",
// messagingSenderId: "650071678820",
// appId: "1:650071678820:web:ce50538bf46632d46c6471",
// measurementId: "G-6JHQ47S9DD"
// };
// /* qa: hpos-qa */
// const firebaseConfig = {
// apiKey: "AIzaSyCF7BNZ5vOMQIpKRi_vxquzWP5pIjcb59I",
// authDomain: "hpos-qa.firebaseapp.com",
// projectId: "hpos-qa",
// storageBucket: "hpos-qa.appspot.com",
// messagingSenderId: "1004619739289",
// appId: "1:1004619739289:web:c3ee0c0127f0d073e5c808",
// measurementId: "G-4MSTJHE64W"
// };
/* preprod */
const firebaseConfig = { const firebaseConfig = {
apiKey: "AIzaSyBFl_YkJ5PMIvMY3G70313SyrqemjFnUv8", apiKey: "AIzaSyBFl_YkJ5PMIvMY3G70313SyrqemjFnUv8",
authDomain: "hpos-af3cc.firebaseapp.com", authDomain: "hpos-af3cc.firebaseapp.com",
@@ -51,25 +28,25 @@ const firebaseConfig = {
// /* preprod */ // /* preprod */
// const firebaseConfig = { // const firebaseConfig = {
// apiKey: "AIzaSyB2-suWmKh2PgQbRmx7rzPjYhgoovQIsQ8", // apiKey: "AIzaSyBFl_YkJ5PMIvMY3G70313SyrqemjFnUv8",
// authDomain: "hpos-preprod.firebaseapp.com", // authDomain: "hpos-af3cc.firebaseapp.com",
// projectId: "hpos-preprod", // projectId: "hpos-af3cc",
// storageBucket: "hpos-preprod.appspot.com", // storageBucket: "hpos-af3cc.appspot.com",
// messagingSenderId: "121176529204", // messagingSenderId: "650071678820",
// appId: "1:121176529204:web:6c0db8e642992192bbed61", // appId: "1:650071678820:web:ce50538bf46632d46c6471",
// measurementId: "G-GYM6LRQ8KR" // measurementId: "G-6JHQ47S9DD"
// }; // };
// /* prod */ // /* prod */
// const firebaseConfig = { // const firebaseConfig = {
// apiKey: "AIzaSyBF4pLZReAedU4dWX1eRJNFNIaOIz2xk4s", // apiKey: "AIzaSyBF4pLZReAedU4dWX1eRJNFNIaOIz2xk4s",
// authDomain: "hpos-prod.firebaseapp.com", // authDomain: "hpos-prod.firebaseapp.com",
// projectId: "hpos-prod", // projectId: "hpos-prod",
// storageBucket: "hpos-prod.appspot.com", // storageBucket: "hpos-prod.appspot.com",
// messagingSenderId: "1012719870714", // messagingSenderId: "1012719870714",
// appId: "1:1012719870714:web:fcd00acef93f6612de5f43", // appId: "1:1012719870714:web:fcd00acef93f6612de5f43",
// measurementId: "G-B0NZ7DEF69" // measurementId: "G-B0NZ7DEF69"
// }; // };
const app = initializeApp(firebaseConfig); const app = initializeApp(firebaseConfig);

View File

@@ -7,13 +7,14 @@ import Devices from '../components/Devices';
import { Download, FactCheck } from '@mui/icons-material'; import { Download, FactCheck } from '@mui/icons-material';
import ExportData from '../components/ExportData'; import ExportData from '../components/ExportData';
import Registration from '../components/Registration'; import Registration from '../components/Registration';
import { FaAndroid, FaArrowCircleLeft, FaBars, FaBezierCurve, FaChalkboardTeacher, FaChartArea, FaChartLine, FaCheck, FaExclamation, FaFlask, FaGolfBall, FaPhone, FaQuestionCircle, FaSearch, FaUser } from 'react-icons/fa'; import { FaAndroid, FaArrowCircleLeft, FaBars, FaBezierCurve, FaChalkboardTeacher, FaChartArea, FaChartLine, FaCheck, FaCommentAlt, FaExclamation, FaFlask, FaGolfBall, FaPhone, FaQuestionCircle, FaSearch, FaUser } from 'react-icons/fa';
import AppInstallation from '../components/AppInstallation'; import AppInstallation from '../components/AppInstallation';
import Samples from '../components/Samples'; import Samples from '../components/Samples';
import Precision from '../components/Precision'; import Precision from '../components/Precision';
import Accuracy from '../components/Accuracy'; import Accuracy from '../components/Accuracy';
import CurveFit from '../components/CurveFit'; import CurveFit from '../components/CurveFit';
import Help from '../components/Help'; import Help from '../components/Help';
import Gemini from '../components/Gemini';
const appRoutes = [ const appRoutes = [
{ {
@@ -89,7 +90,7 @@ const appRoutes = [
element: <Accuracy />, element: <Accuracy />,
state: "autoanalysis", state: "autoanalysis",
sidebarProps: { sidebarProps: {
displayText: "Auto Analysis (NEW)", displayText: "Auto Analysis",
icon: <FaChartLine /> icon: <FaChartLine />
} }
}, },
@@ -102,6 +103,15 @@ const appRoutes = [
// icon: <FaBezierCurve /> // icon: <FaBezierCurve />
// } // }
// }, // },
{
path: "/chat",
element: <Gemini />,
state: "chat",
sidebarProps: {
displayText: "Gemini",
icon: <FaCommentAlt />
}
},
{ {
path: "/helpcenter", path: "/helpcenter",
element: <Help />, element: <Help />,