Spaces:
Configuration error
Configuration error
| 'use client'; | |
| /*eslint-disable*/ | |
| import Link from '@/components/link/Link'; | |
| import MessageBoxChat from '@/components/MessageBox'; | |
| import { ChatBody, OpenAIModel } from '@/types/types'; | |
| import { | |
| Accordion, | |
| AccordionButton, | |
| AccordionIcon, | |
| AccordionItem, | |
| AccordionPanel, | |
| Box, | |
| Button, | |
| Flex, | |
| Icon, | |
| Image, | |
| Img, | |
| Input, | |
| Text, | |
| useColorModeValue, | |
| } from '@chakra-ui/react'; | |
| import { useEffect, useState } from 'react'; | |
| import { MdAutoAwesome, MdBolt, MdEdit, MdPerson } from 'react-icons/md'; | |
| import Bg from '../public/img/chat/bg-image.png'; | |
| export default function Chat(props: { apiKeyApp: string }) { | |
| // *** If you use .env.local variable for your API key, method which we recommend, use the apiKey variable commented below | |
| const { apiKeyApp } = props; | |
| // Input States | |
| const [inputOnSubmit, setInputOnSubmit] = useState<string>(''); | |
| const [inputCode, setInputCode] = useState<string>(''); | |
| // Response message | |
| const [outputCode, setOutputCode] = useState<string>(''); | |
| // ChatGPT model | |
| const [model, setModel] = useState<OpenAIModel>('gpt-3.5-turbo'); | |
| // Loading state | |
| const [loading, setLoading] = useState<boolean>(false); | |
| // API Key | |
| // const [apiKey, setApiKey] = useState<string>(apiKeyApp); | |
| const borderColor = useColorModeValue('gray.200', 'whiteAlpha.200'); | |
| const inputColor = useColorModeValue('navy.700', 'white'); | |
| const iconColor = useColorModeValue('brand.500', 'white'); | |
| const bgIcon = useColorModeValue( | |
| 'linear-gradient(180deg, #FBFBFF 0%, #CACAFF 100%)', | |
| 'whiteAlpha.200', | |
| ); | |
| const brandColor = useColorModeValue('brand.500', 'white'); | |
| const buttonBg = useColorModeValue('white', 'whiteAlpha.100'); | |
| const gray = useColorModeValue('gray.500', 'white'); | |
| const buttonShadow = useColorModeValue( | |
| '14px 27px 45px rgba(112, 144, 176, 0.2)', | |
| 'none', | |
| ); | |
| const textColor = useColorModeValue('navy.700', 'white'); | |
| const placeholderColor = useColorModeValue( | |
| { color: 'gray.500' }, | |
| { color: 'whiteAlpha.600' }, | |
| ); | |
| const handleTranslate = async () => { | |
| const apiKey = apiKeyApp; | |
| setInputOnSubmit(inputCode); | |
| // Chat post conditions(maximum number of characters, valid message etc.) | |
| const maxCodeLength = model === 'gpt-3.5-turbo' ? 700 : 700; | |
| if (!apiKeyApp?.includes('sk-') && !apiKey?.includes('sk-')) { | |
| alert('Please enter an API key.'); | |
| return; | |
| } | |
| if (!inputCode) { | |
| alert('Please enter your message.'); | |
| return; | |
| } | |
| if (inputCode.length > maxCodeLength) { | |
| alert( | |
| `Please enter code less than ${maxCodeLength} characters. You are currently at ${inputCode.length} characters.`, | |
| ); | |
| return; | |
| } | |
| setOutputCode(' '); | |
| setLoading(true); | |
| const controller = new AbortController(); | |
| const body: ChatBody = { | |
| inputCode, | |
| model, | |
| apiKey, | |
| }; | |
| // -------------- Fetch -------------- | |
| const response = await fetch('/api/chatAPI', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| signal: controller.signal, | |
| body: JSON.stringify(body), | |
| }); | |
| if (!response.ok) { | |
| setLoading(false); | |
| if (response) { | |
| alert( | |
| 'Something went wrong went fetching from the API. Make sure to use a valid API key.', | |
| ); | |
| } | |
| return; | |
| } | |
| const data = response.body; | |
| if (!data) { | |
| setLoading(false); | |
| alert('Something went wrong'); | |
| return; | |
| } | |
| const reader = data.getReader(); | |
| const decoder = new TextDecoder(); | |
| let done = false; | |
| while (!done) { | |
| setLoading(true); | |
| const { value, done: doneReading } = await reader.read(); | |
| done = doneReading; | |
| const chunkValue = decoder.decode(value); | |
| setOutputCode((prevCode) => prevCode + chunkValue); | |
| } | |
| setLoading(false); | |
| }; | |
| // -------------- Copy Response -------------- | |
| // const copyToClipboard = (text: string) => { | |
| // const el = document.createElement('textarea'); | |
| // el.value = text; | |
| // document.body.appendChild(el); | |
| // el.select(); | |
| // document.execCommand('copy'); | |
| // document.body.removeChild(el); | |
| // }; | |
| // *** Initializing apiKey with .env.local value | |
| // useEffect(() => { | |
| // ENV file verison | |
| // const apiKeyENV = process.env.NEXT_PUBLIC_OPENAI_API_KEY | |
| // if (apiKey === undefined || null) { | |
| // setApiKey(apiKeyENV) | |
| // } | |
| // }, []) | |
| const handleChange = (Event: any) => { | |
| setInputCode(Event.target.value); | |
| }; | |
| return ( | |
| <Flex | |
| w="100%" | |
| pt={{ base: '70px', md: '0px' }} | |
| direction="column" | |
| position="relative" | |
| > | |
| <Img | |
| src={Bg.src} | |
| position={'absolute'} | |
| w="350px" | |
| left="50%" | |
| top="50%" | |
| transform={'translate(-50%, -50%)'} | |
| /> | |
| <Flex | |
| direction="column" | |
| mx="auto" | |
| w={{ base: '100%', md: '100%', xl: '100%' }} | |
| minH={{ base: '75vh', '2xl': '85vh' }} | |
| maxW="1000px" | |
| > | |
| {/* Model Change */} | |
| <Flex direction={'column'} w="100%" mb={outputCode ? '20px' : 'auto'}> | |
| <Flex | |
| mx="auto" | |
| zIndex="2" | |
| w="max-content" | |
| mb="20px" | |
| borderRadius="60px" | |
| > | |
| <Flex | |
| cursor={'pointer'} | |
| transition="0.3s" | |
| justify={'center'} | |
| align="center" | |
| bg={model === 'gpt-3.5-turbo' ? buttonBg : 'transparent'} | |
| w="174px" | |
| h="70px" | |
| boxShadow={model === 'gpt-3.5-turbo' ? buttonShadow : 'none'} | |
| borderRadius="14px" | |
| color={textColor} | |
| fontSize="18px" | |
| fontWeight={'700'} | |
| onClick={() => setModel('gpt-3.5-turbo')} | |
| > | |
| <Flex | |
| borderRadius="full" | |
| justify="center" | |
| align="center" | |
| bg={bgIcon} | |
| me="10px" | |
| h="39px" | |
| w="39px" | |
| > | |
| <Icon | |
| as={MdAutoAwesome} | |
| width="20px" | |
| height="20px" | |
| color={iconColor} | |
| /> | |
| </Flex> | |
| GPT-3.5 | |
| </Flex> | |
| <Flex | |
| cursor={'pointer'} | |
| transition="0.3s" | |
| justify={'center'} | |
| align="center" | |
| bg={model === 'gpt-4' ? buttonBg : 'transparent'} | |
| w="164px" | |
| h="70px" | |
| boxShadow={model === 'gpt-4' ? buttonShadow : 'none'} | |
| borderRadius="14px" | |
| color={textColor} | |
| fontSize="18px" | |
| fontWeight={'700'} | |
| onClick={() => setModel('gpt-4')} | |
| > | |
| <Flex | |
| borderRadius="full" | |
| justify="center" | |
| align="center" | |
| bg={bgIcon} | |
| me="10px" | |
| h="39px" | |
| w="39px" | |
| > | |
| <Icon | |
| as={MdBolt} | |
| width="20px" | |
| height="20px" | |
| color={iconColor} | |
| /> | |
| </Flex> | |
| GPT-4 | |
| </Flex> | |
| </Flex> | |
| <Accordion color={gray} allowToggle w="100%" my="0px" mx="auto"> | |
| <AccordionItem border="none"> | |
| <AccordionButton | |
| borderBottom="0px solid" | |
| maxW="max-content" | |
| mx="auto" | |
| _hover={{ border: '0px solid', bg: 'none' }} | |
| _focus={{ border: '0px solid', bg: 'none' }} | |
| > | |
| <Box flex="1" textAlign="left"> | |
| <Text color={gray} fontWeight="500" fontSize="sm"> | |
| No plugins added | |
| </Text> | |
| </Box> | |
| <AccordionIcon color={gray} /> | |
| </AccordionButton> | |
| <AccordionPanel mx="auto" w="max-content" p="0px 0px 10px 0px"> | |
| <Text | |
| color={gray} | |
| fontWeight="500" | |
| fontSize="sm" | |
| textAlign={'center'} | |
| > | |
| This is a cool text example. | |
| </Text> | |
| </AccordionPanel> | |
| </AccordionItem> | |
| </Accordion> | |
| </Flex> | |
| {/* Main Box */} | |
| <Flex | |
| direction="column" | |
| w="100%" | |
| mx="auto" | |
| display={outputCode ? 'flex' : 'none'} | |
| mb={'auto'} | |
| > | |
| <Flex w="100%" align={'center'} mb="10px"> | |
| <Flex | |
| borderRadius="full" | |
| justify="center" | |
| align="center" | |
| bg={'transparent'} | |
| border="1px solid" | |
| borderColor={borderColor} | |
| me="20px" | |
| h="40px" | |
| minH="40px" | |
| minW="40px" | |
| > | |
| <Icon | |
| as={MdPerson} | |
| width="20px" | |
| height="20px" | |
| color={brandColor} | |
| /> | |
| </Flex> | |
| <Flex | |
| p="22px" | |
| border="1px solid" | |
| borderColor={borderColor} | |
| borderRadius="14px" | |
| w="100%" | |
| zIndex={'2'} | |
| > | |
| <Text | |
| color={textColor} | |
| fontWeight="600" | |
| fontSize={{ base: 'sm', md: 'md' }} | |
| lineHeight={{ base: '24px', md: '26px' }} | |
| > | |
| {inputOnSubmit} | |
| </Text> | |
| <Icon | |
| cursor="pointer" | |
| as={MdEdit} | |
| ms="auto" | |
| width="20px" | |
| height="20px" | |
| color={gray} | |
| /> | |
| </Flex> | |
| </Flex> | |
| <Flex w="100%"> | |
| <Flex | |
| borderRadius="full" | |
| justify="center" | |
| align="center" | |
| bg={'linear-gradient(15.46deg, #4A25E1 26.3%, #7B5AFF 86.4%)'} | |
| me="20px" | |
| h="40px" | |
| minH="40px" | |
| minW="40px" | |
| > | |
| <Icon | |
| as={MdAutoAwesome} | |
| width="20px" | |
| height="20px" | |
| color="white" | |
| /> | |
| </Flex> | |
| <MessageBoxChat output={outputCode} /> | |
| </Flex> | |
| </Flex> | |
| {/* Chat Input */} | |
| <Flex | |
| ms={{ base: '0px', xl: '60px' }} | |
| mt="20px" | |
| justifySelf={'flex-end'} | |
| > | |
| <Input | |
| minH="54px" | |
| h="100%" | |
| border="1px solid" | |
| borderColor={borderColor} | |
| borderRadius="45px" | |
| p="15px 20px" | |
| me="10px" | |
| fontSize="sm" | |
| fontWeight="500" | |
| _focus={{ borderColor: 'none' }} | |
| color={inputColor} | |
| _placeholder={placeholderColor} | |
| placeholder="Type your message here..." | |
| onChange={handleChange} | |
| /> | |
| <Button | |
| variant="primary" | |
| py="20px" | |
| px="16px" | |
| fontSize="sm" | |
| borderRadius="45px" | |
| ms="auto" | |
| w={{ base: '160px', md: '210px' }} | |
| h="54px" | |
| _hover={{ | |
| boxShadow: | |
| '0px 21px 27px -10px rgba(96, 60, 255, 0.48) !important', | |
| bg: | |
| 'linear-gradient(15.46deg, #4A25E1 26.3%, #7B5AFF 86.4%) !important', | |
| _disabled: { | |
| bg: 'linear-gradient(15.46deg, #4A25E1 26.3%, #7B5AFF 86.4%)', | |
| }, | |
| }} | |
| onClick={handleTranslate} | |
| isLoading={loading ? true : false} | |
| > | |
| Submit | |
| </Button> | |
| </Flex> | |
| <Flex | |
| justify="center" | |
| mt="20px" | |
| direction={{ base: 'column', md: 'row' }} | |
| alignItems="center" | |
| > | |
| <Text fontSize="xs" textAlign="center" color={gray}> | |
| Free Research Preview. ChatGPT may produce inaccurate information | |
| about people, places, or facts. | |
| </Text> | |
| <Link href="https://help.openai.com/en/articles/6825453-chatgpt-release-notes"> | |
| <Text | |
| fontSize="xs" | |
| color={textColor} | |
| fontWeight="500" | |
| textDecoration="underline" | |
| > | |
| ChatGPT May 12 Version | |
| </Text> | |
| </Link> | |
| </Flex> | |
| </Flex> | |
| </Flex> | |
| ); | |
| } | |