Spaces:
Runtime error
Runtime error
| import { APIKeyInput } from '@/components/APIKeyInput'; | |
| import { CodeBlock } from '@/components/CodeBlock'; | |
| import { LanguageSelect } from '@/components/LanguageSelect'; | |
| import { ModelSelect } from '@/components/ModelSelect'; | |
| import { TextBlock } from '@/components/TextBlock'; | |
| import { OpenAIModel, TranslateBody } from '@/types/types'; | |
| import Head from 'next/head'; | |
| import { useEffect, useState } from 'react'; | |
| export default function Home() { | |
| const [inputLanguage, setInputLanguage] = useState<string>('JavaScript'); | |
| const [outputLanguage, setOutputLanguage] = useState<string>('Python'); | |
| const [inputCode, setInputCode] = useState<string>(''); | |
| const [outputCode, setOutputCode] = useState<string>(''); | |
| const [model, setModel] = useState<OpenAIModel>('gpt-3.5-turbo'); | |
| const [loading, setLoading] = useState<boolean>(false); | |
| const [hasTranslated, setHasTranslated] = useState<boolean>(false); | |
| const [apiKey, setApiKey] = useState<string>(''); | |
| const handleTranslate = async () => { | |
| const maxCodeLength = model === 'gpt-3.5-turbo' ? 6000 : 12000; | |
| if (!apiKey) { | |
| alert('Please enter an API key.'); | |
| return; | |
| } | |
| if (inputLanguage === outputLanguage) { | |
| alert('Please select different languages.'); | |
| return; | |
| } | |
| if (!inputCode) { | |
| alert('Please enter some code.'); | |
| return; | |
| } | |
| if (inputCode.length > maxCodeLength) { | |
| alert( | |
| `Please enter code less than ${maxCodeLength} characters. You are currently at ${inputCode.length} characters.`, | |
| ); | |
| return; | |
| } | |
| setLoading(true); | |
| setOutputCode(''); | |
| const controller = new AbortController(); | |
| const body: TranslateBody = { | |
| inputLanguage, | |
| outputLanguage, | |
| inputCode, | |
| model, | |
| apiKey, | |
| }; | |
| const response = await fetch('/api/translate', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| signal: controller.signal, | |
| body: JSON.stringify(body), | |
| }); | |
| if (!response.ok) { | |
| setLoading(false); | |
| alert('Something went wrong.'); | |
| 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; | |
| let code = ''; | |
| while (!done) { | |
| const { value, done: doneReading } = await reader.read(); | |
| done = doneReading; | |
| const chunkValue = decoder.decode(value); | |
| code += chunkValue; | |
| setOutputCode((prevCode) => prevCode + chunkValue); | |
| } | |
| setLoading(false); | |
| setHasTranslated(true); | |
| copyToClipboard(code); | |
| }; | |
| 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); | |
| }; | |
| const handleApiKeyChange = (value: string) => { | |
| setApiKey(value); | |
| localStorage.setItem('apiKey', value); | |
| }; | |
| useEffect(() => { | |
| if (hasTranslated) { | |
| handleTranslate(); | |
| } | |
| }, [outputLanguage]); | |
| useEffect(() => { | |
| const apiKey = localStorage.getItem('apiKey'); | |
| if (apiKey) { | |
| setApiKey(apiKey); | |
| } | |
| }, []); | |
| return ( | |
| <> | |
| <Head> | |
| <title>Code Translator</title> | |
| <meta | |
| name="description" | |
| content="Use AI to translate code from one language to another." | |
| /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <link rel="icon" href="/favicon.ico" /> | |
| </Head> | |
| <div className="flex h-full min-h-screen flex-col items-center bg-[#0E1117] px-4 pb-20 text-neutral-200 sm:px-10"> | |
| <div className="mt-10 flex flex-col items-center justify-center sm:mt-20"> | |
| <div className="text-4xl font-bold">AI Code Translator</div> | |
| </div> | |
| <div className="mt-6 text-center text-sm"> | |
| <APIKeyInput apiKey={apiKey} onChange={handleApiKeyChange} /> | |
| </div> | |
| <div className="mt-2 flex items-center space-x-2"> | |
| <ModelSelect model={model} onChange={(value) => setModel(value)} /> | |
| <button | |
| className="w-[140px] cursor-pointer rounded-md bg-violet-500 px-4 py-2 font-bold hover:bg-violet-600 active:bg-violet-700" | |
| onClick={() => handleTranslate()} | |
| disabled={loading} | |
| > | |
| {loading ? 'Translating...' : 'Translate'} | |
| </button> | |
| </div> | |
| <div className="mt-2 text-center text-xs"> | |
| {loading | |
| ? 'Translating...' | |
| : hasTranslated | |
| ? 'Output copied to clipboard!' | |
| : 'Enter some code and click "Translate"'} | |
| </div> | |
| <div className="mt-6 flex w-full max-w-[1200px] flex-col justify-between sm:flex-row sm:space-x-4"> | |
| <div className="h-100 flex flex-col justify-center space-y-2 sm:w-2/4"> | |
| <div className="text-center text-xl font-bold">Input</div> | |
| <LanguageSelect | |
| language={inputLanguage} | |
| onChange={(value) => { | |
| setInputLanguage(value); | |
| setHasTranslated(false); | |
| setInputCode(''); | |
| setOutputCode(''); | |
| }} | |
| /> | |
| {inputLanguage === 'Natural Language' ? ( | |
| <TextBlock | |
| text={inputCode} | |
| editable={!loading} | |
| onChange={(value) => { | |
| setInputCode(value); | |
| setHasTranslated(false); | |
| }} | |
| /> | |
| ) : ( | |
| <CodeBlock | |
| code={inputCode} | |
| editable={!loading} | |
| onChange={(value) => { | |
| setInputCode(value); | |
| setHasTranslated(false); | |
| }} | |
| /> | |
| )} | |
| </div> | |
| <div className="mt-8 flex h-full flex-col justify-center space-y-2 sm:mt-0 sm:w-2/4"> | |
| <div className="text-center text-xl font-bold">Output</div> | |
| <LanguageSelect | |
| language={outputLanguage} | |
| onChange={(value) => { | |
| setOutputLanguage(value); | |
| setOutputCode(''); | |
| }} | |
| /> | |
| {outputLanguage === 'Natural Language' ? ( | |
| <TextBlock text={outputCode} /> | |
| ) : ( | |
| <CodeBlock code={outputCode} /> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| </> | |
| ); | |
| } | |