UNPKG

servibot

Version:

This is the official API for ServiBot, an advanced AI chatbot which provides enhanced customer service to businesses.

816 lines (785 loc) 27.8 kB
"use client"; import firebase from "firebase/compat/app"; import "firebase/compat/auth"; import "firebase/compat/firestore"; import "firebase/compat/storage"; import { arrayUnion, arrayRemove, serverTimestamp, increment, } from "firebase/firestore"; import { Button, Flex, Image, Text, Input, InputGroup, InputRightElement, Spinner, ChakraProvider, useToast, } from "@chakra-ui/react"; import { useEffect, useState, useReducer, useRef } from "react"; import OpenAI from "openai"; import { ChevronDownIcon } from "@chakra-ui/icons"; const ServiBot = (props) => { const toast = useToast(); const bottomRef = useRef(null); const [color, setColor] = useState(""); const [display, setDisplay] = useState(false); const [label, setLabel] = useState([true, "Label"]); const [companyName, setCompanyName] = useState(""); const [messages, setMessages] = useState([ `Welcome to our chatbot, how can I help you today?`, ]); const [animationTrigger, setAnimationTrigger] = useState(false); const [img, setImg] = useState(""); const [img2, setImg2] = useState("one"); const [txt, setTxt] = useState(""); const [position, setPosition] = useState(""); const [prompts, setPrompts] = useState([]); const [show, setShow] = useState(false); const [toxt, setToxt] = useState(""); const [resload, setResload] = useState(false); const [ready, setReady] = useState(false); const [chatImg, setChatImg] = useState(""); const [xImg, setXImg] = useState(""); const [avatarImg, setAvatarImg] = useState(""); const [logoImg, setLogoImg] = useState(""); const [sendImg, setSendImg] = useState(""); const firebaseConfig = { apiKey: "AIzaSyANzBgpkTRm4wWVTXvOGN06_4moH30yYW0", authDomain: "servibot-35220.firebaseapp.com", projectId: "servibot-35220", storageBucket: "servibot-35220.appspot.com", messagingSenderId: "568351336305", appId: "1:568351336305:web:a1026f44a414a51b3938d0", measurementId: "G-CV36XS4YHD", }; const firebaseApp = firebase.initializeApp(firebaseConfig); // Use these for db & auth const db = firebaseApp.firestore(); const auth = firebase.auth(); const storage = firebase.storage(); useEffect(() => { if (props.id != "") { db.collection("companies") .doc(props.id) .get() .then((val) => { if (val.exists) { if (val.get("respondersImage") != "") { storage .ref(val.get("respondersImage")) .getDownloadURL() .then((url) => { setImg2(url); }); } else { setImg2(""); } // split up storage stuff in case what and change chatimg stuff as well storage .ref("/logo.png") .getDownloadURL() .then((url) => { setLogoImg(url); storage .ref("/avatar.png") .getDownloadURL() .then((url) => { setAvatarImg(url); storage .ref("/x.png") .getDownloadURL() .then((url) => { setXImg(url); storage .ref("/send.png") .getDownloadURL() .then((url) => { setSendImg(url); storage .ref("/chat.png") .getDownloadURL() .then((url) => { setChatImg(url); setReady(true); }); }); }); }); }); setPrompts(val.get("prompts")); setColor(val.get("color")); setDisplay(val.get("display")); setLabel(val.get("label")); setCompanyName(val.get("companyName")); setPosition(val.get("position")); } else { console.error("This is an invalid API"); console.log( "Please try again or contact us if it continually doesn't work" ); } }); } else { console.error("This is an invalid id"); } }, []); useEffect(() => {}, [messages]); useEffect(() => {}, [ready]); useEffect(() => {}, [show]); // useEffect(() => {}, [img]); useEffect(() => {}, [img2]); useEffect(() => {}, [chatImg]); useEffect(() => {}, [xImg]); useEffect(() => {}, [avatarImg]); useEffect(() => {}, [logoImg]); useEffect(() => {}, [sendImg]); useEffect(() => {}, [resload]); const openAIOutput = async (e) => { e.preventDefault(); setMessages((prevMessages) => [...prevMessages, n]); let n = toxt; setToxt(""); setResload(true); let maxTokens = 15000; db.collection("OpenAI") .doc("API") .get() .then(async (val) => { const apiK = val.get("Key"); let openai = new OpenAI({ apiKey: apiK, dangerouslyAllowBrowser: true, }); let model = "gpt-3.5-turbo-16k"; let temp = 0.85; try { // Send a request to the OpenAI API to generate text const response = await openai.chat.completions.create({ model: model, // prompt: prompt, messages: [ { role: "user", content: `Answer the text message: ${n} with another text message (presumably shorter) as a welcoming employee of a company. \n\nAnswer the message based on the information about the company:\n${ [...prompts][0] }. Answer the questions like a normal person would. Try to connect with others and be the most attractive employee you can be for a company. If a question is personal, feel free to answer in a personal way. If possible try to keep text messages shorter.`, }, ], max_tokens: maxTokens, temperature: temp, }); // console.log([...prompts][0]); // console.log(`request cost: ${response.usage.total_tokens} tokens`); // console.log(response.choices[0].message.content); setResload(false); setMessages((prevMessages) => [ ...prevMessages, response.choices[0].message.content, ]); setToxt(""); return; } catch (err) { console.log("This is an error"); toast({ title: "Cannot generate more code", duration: 3000, isClosable: true, status: "error", }); setResload(false); throw err; } }) .catch((err) => { toast({ title: "There has been an error", duration: 3000, isClosable: true, status: "error", }); console.log(err.message); }); }; const scrollToBottom = () => { if (bottomRef.current) { bottomRef.current.scrollTop = bottomRef.current.scrollHeight; } }; useEffect(scrollToBottom, [messages]); if (ready) { return ( <ChakraProvider> {position == "left" ? ( <Flex position={"fixed"} left={0} top={"calc(100vh - 490px)"} direction={"column"} width={330} height={450} zIndex={2000} gap={3} margin={5} > {show ? ( <Flex direction={"column"} width={"100%"} height={"82.5%"} // boxShadow={"0 0 5px 2px #bcbcbc"} boxShadow={"0 0 3px 1px #bcbcbc"} borderRadius={5} // zIndex={2000} position={"relative"} > <Flex w={"full"} height={10} justifyContent={"flex-end"} alignItems={"center"} backgroundColor={ color == "blue" ? "#3D96EE" : color == "green" ? "#37D35D" : color == "red" ? "#F44B4B" : color == "orange" ? "#E37500" : color == "purple" ? "#913AD6" : color == "yellow" ? "#C1C545" : "#3D96EE" } borderTopRadius={5} > <Button colorScheme={"transparent"} _hover={{ opacity: 0.8, }} onClick={() => setShow(false)} > <ChevronDownIcon color={"white"} /> </Button> </Flex> <Flex direction={"column"} width={"100%"} padding={2} overflowY={"scroll"} backgroundColor={"#ffffff"} gap={2} ref={bottomRef} > {messages.map((message, index) => ( <Flex width={"100%"} justifyContent={"left"} alignItems={"center"} gap={2} > <Image // src={img == "" ? "/avatar.png" : img} alt={"Avatar image"} src={ index % 2 == 0 ? img2 != "" ? img2 : logoImg : // : img != "" // ? img avatarImg } boxShadow={"0 0 3px 1px #dfdfdf"} w={30} h={30} borderRadius={"50%"} /> <Flex alignItems={"center"} justifyContent={"center"} backgroundColor={index % 2 == 0 ? "#dfdfdf" : "#37C34E"} borderRadius={15} pl={3} pr={3} pt={1} pb={1} > <Text textAlign={"left"} color={index % 2 == 0 ? "#000000" : "#ffffff"} fontSize={"11pt"} > {message} </Text> </Flex> </Flex> /* Waiting for AI notification thing */ /* <Flex direction={"column"} alignItems={"center"} justifyContent={"center"} width={"100%"} > <Text textAlign={"center"} fontSize={"10pt"} fontWeight={700} > It may take a few seconds, please wait... </Text> </Flex> */ ))} </Flex> <Flex flex="1" backgroundColor={"#ffffff"} /> <InputGroup size="md" w="100%" h="40px" backgroundColor={"#ffffff"} borderBottomRadius={5} borderTop={"1px solid #efefef"} borderRadius={0} > <Flex alignItems={"center"} justifyContent={"center"} width={"100%"} as={"form"} onSubmit={(e) => openAIOutput(e)} > <Input type="text" placeholder="Type here" readOnly={resload} value={toxt} onChange={(e) => setToxt(e.target.value)} borderTopRadius={0} pr={8} required // value={inputValue} // onChange={handleInputChange} /> <InputRightElement> <Button h="100%" size="sm" type={"submit"} colorScheme={"transparent"} w={20} _hover={{ cursor: "pointer", opacity: 0.8, }} > {resload == false ? ( <Image src={sendImg} alt={"Send it here"} /> ) : ( <Spinner color="black" size={"sm"} /> )} </Button> </InputRightElement> </Flex> </InputGroup> </Flex> ) : ( <Flex flex="1" /> )} {display && ( <Flex gap={3} alignItems={"center"} justifyContent={position == "right" ? "right" : "left"} > {[...label][0] && txt != "" && position == "right" && ( <Flex backgroundColor={"white"} paddingLeft={3} paddingRight={3} boxShadow={"0 0 5px 2px #bcbcbc"} borderRadius={5} as={Button} colorScheme={"transparent"} color={"black"} fontWeight={400} onClick={() => setShow(!show)} // zIndex={2000} // _hover={{ // opacity: 0.8, // boxShadow: "0 0 3px 1px #bcbcbc", // }} > <Text>{txt}</Text> </Flex> )} <Button colorScheme={"transparent"} // _hover={{ // opacity: 0.8, // boxShadow: "none", // }} borderRadius={"50%"} padding={4} width={65} height={65} // Uncomment later line below // boxShadow={"0 0 5px 2px #bcbcbc"} // zIndex={2000} backgroundColor={ color == "blue" ? "#3D96EE" : color == "green" ? "#37D35D" : color == "red" ? "#F44B4B" : color == "orange" ? "#E37500" : color == "purple" ? "#913AD6" : color == "yellow" ? "#C1C545" : "#3D96EE" } _hover={{ opacity: 0.95, }} onClick={() => { setAnimationTrigger(false); // Trigger the animation setTimeout(() => setAnimationTrigger(true), 10); setShow(!show); }} sx={{ animation: animationTrigger ? "bounce 0.3s ease" : "none", "@keyframes bounce": { "0%": { transform: "scale(1)" }, "50%": { transform: "scale(1.1)" }, "100%": { transform: "scale(1)" }, }, }} > {chatImg != "" && ( <Image src={!show ? chatImg : xImg} alt={"Chat icon"} /> )} </Button> {[...label][0] && txt != "" && position == "left" && ( <Flex backgroundColor={"white"} paddingLeft={3} paddingRight={3} boxShadow={"0 0 5px 2px #bcbcbc"} borderRadius={5} as={Button} colorScheme={"transparent"} color={"black"} _hover={{ opacity: 0.95, }} fontWeight={400} // zIndex={2000} // _hover={{ // opacity: 0.8, // boxShadow: "0 0 3px 1px #bcbcbc", // }} > <Text>{txt}</Text> </Flex> )} </Flex> )} </Flex> ) : ( <Flex position={"fixed"} left={"calc(100vw - 370px)"} top={"calc(100vh - 490px)"} direction={"column"} width={330} height={450} gap={3} margin={5} zIndex={2000} > {show ? ( <Flex direction={"column"} width={"100%"} height={"82.5%"} position={"relative"} // boxShadow={"0 0 5px 2px #bcbcbc"} boxShadow={"0 0 3px 1px #bcbcbc"} borderRadius={5} // zIndex={2000} > <Flex w={"full"} height={10} justifyContent={"flex-end"} alignItems={"center"} backgroundColor={ color == "blue" ? "#3D96EE" : color == "green" ? "#37D35D" : color == "red" ? "#F44B4B" : color == "orange" ? "#E37500" : color == "purple" ? "#913AD6" : color == "yellow" ? "#C1C545" : "#3D96EE" } borderTopRadius={5} > <Button colorScheme={"transparent"} _hover={{ opacity: 0.8, }} onClick={() => setShow(false)} > <ChevronDownIcon color={"white"} /> </Button> </Flex> <Flex direction={"column"} width={"100%"} padding={2} overflowY={"scroll"} gap={2} backgroundColor={"#ffffff"} ref={bottomRef} > {messages.map((message, index) => ( <Flex width={"100%"} justifyContent={"left"} alignItems={"center"} gap={2} > <Image // src={img == "" ? "/avatar.png" : img} src={ index % 2 == 0 ? img2 != "" ? img2 : logoImg : img != "" ? img : avatarImg } boxShadow={"0 0 3px 1px #dfdfdf"} w={30} h={30} borderRadius={"50%"} alt={"Profile Image"} /> <Flex alignItems={"center"} justifyContent={"center"} backgroundColor={index % 2 == 0 ? "#dfdfdf" : "#37C34E"} borderRadius={15} pl={3} pr={3} pt={1} pb={1} > <Text textAlign={"left"} color={index % 2 == 0 ? "#000000" : "#ffffff"} fontSize={"11pt"} > {message} </Text> </Flex> </Flex> /* Waiting for AI notification thing */ /* <Flex direction={"column"} alignItems={"center"} justifyContent={"center"} width={"100%"} > <Text textAlign={"center"} fontSize={"10pt"} fontWeight={700} > It may take a few seconds, please wait... </Text> </Flex> */ ))} </Flex> <Flex flex="1" backgroundColor={"#ffffff"} /> <InputGroup size="md" w="100%" h="40px" borderTop={"1px solid #efefef"} borderRadius={0} backgroundColor={"#ffffff"} borderBottomRadius={5} > <Flex alignItems={"center"} justifyContent={"center"} width={"100%"} as={"form"} onSubmit={(e) => openAIOutput(e)} > <Input type="text" placeholder="Type here" readOnly={resload} value={toxt} onChange={(e) => setToxt(e.target.value)} borderTopRadius={0} pr={8} required // value={inputValue} // onChange={handleInputChange} /> <InputRightElement> <Button h="100%" size="sm" type={"submit"} colorScheme={"transparent"} w={20} _hover={{ cursor: "pointer", opacity: 0.8, }} > {resload == false ? ( <Image src={sendImg} alt={"Send it here"} /> ) : ( <Spinner color="black" size={"sm"} /> )} </Button> </InputRightElement> </Flex> </InputGroup> </Flex> ) : ( <Flex flex="1" /> )} {display && ( <Flex gap={3} alignItems={"center"} justifyContent={position == "right" ? "right" : "left"} > {[...label][0] && txt != "" && position == "right" && ( <Flex backgroundColor={"white"} paddingLeft={3} paddingRight={3} boxShadow={"0 0 5px 2px #bcbcbc"} borderRadius={5} as={Button} colorScheme={"transparent"} color={"black"} fontWeight={400} _hover={{ opacity: 0.95, }} onClick={() => setShow(!show)} // zIndex={2000} // _hover={{ // opacity: 0.8, // boxShadow: "0 0 3px 1px #bcbcbc", // }} > <Text>{txt}</Text> </Flex> )} <Button colorScheme={"transparent"} // _hover={{ // opacity: 0.8, // boxShadow: "none", // }} borderRadius={"50%"} padding={4} width={65} height={65} // Uncomment later line below // boxShadow={"0 0 5px 2px #bcbcbc"} // zIndex={2000} backgroundColor={ color == "blue" ? "#3D96EE" : color == "green" ? "#37D35D" : color == "red" ? "#F44B4B" : color == "orange" ? "#E37500" : color == "purple" ? "#913AD6" : color == "yellow" ? "#C1C545" : "#3D96EE" } _hover={{ opacity: 0.95, }} onClick={() => { setAnimationTrigger(false); // Trigger the animation setTimeout(() => setAnimationTrigger(true), 10); setShow(!show); }} sx={{ animation: animationTrigger ? "bounce 0.3s ease" : "none", "@keyframes bounce": { "0%": { transform: "scale(1)" }, "50%": { transform: "scale(1.1)" }, "100%": { transform: "scale(1)" }, }, }} > {chatImg != "" && ( <Image src={!show ? chatImg : xImg} alt={"Chat icon"} /> )} </Button> {[...label][0] && txt != "" && position == "left" && ( <Flex backgroundColor={"white"} paddingLeft={3} paddingRight={3} boxShadow={"0 0 5px 2px #bcbcbc"} borderRadius={5} as={Button} // zIndex={2000} colorScheme={"transparent"} color={"black"} fontWeight={400} // _hover={{ // opacity: 0.8, // boxShadow: "0 0 3px 1px #bcbcbc", // }} > <Text>{txt}</Text> </Flex> )} </Flex> )} </Flex> )} </ChakraProvider> ); } }; export default ServiBot;