Skip to content

Commit 4c174f6

Browse files
Initial commit
Created from https://vercel.com/new
0 parents  commit 4c174f6

27 files changed

Lines changed: 8545 additions & 0 deletions

.env.local.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
OPENAI_API_KEY=YOUR_KEY_HERE

.eslintrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "next/core-web-vitals"
3+
}

.gitignore

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# next.js
12+
/.next/
13+
/out/
14+
15+
# production
16+
/build
17+
18+
# misc
19+
.DS_Store
20+
*.pem
21+
22+
# debug
23+
npm-debug.log*
24+
yarn-debug.log*
25+
yarn-error.log*
26+
.pnpm-debug.log*
27+
28+
# local env files
29+
.env*.local
30+
31+
# vercel
32+
.vercel
33+
34+
# typescript
35+
*.tsbuildinfo
36+
next-env.d.ts
37+
38+
yarn.lock

Dockerfile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Use the official Node.js image as the base image
2+
FROM node:14
3+
4+
# Set the working directory inside the container
5+
WORKDIR /app
6+
7+
# Copy package.json and package-lock.json to the working directory
8+
COPY package*.json ./
9+
10+
# Install the dependencies
11+
RUN npm ci
12+
13+
# Copy the rest of the application code to the working directory
14+
COPY . .
15+
16+
# Expose the port the app will run on
17+
EXPOSE 3001
18+
19+
# Start the application
20+
CMD ["npm", "run", "dev"]

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# AI Code Translator
2+
3+
Use AI to translate code from one language to another.
4+
5+
![AI Code Translator](./public/screenshot.png)
6+
7+
## Running Locally
8+
9+
**1. Clone Repo**
10+
11+
```bash
12+
git clone https://github.com/mckaywrigley/ai-code-translator.git
13+
```
14+
15+
**2. Install Dependencies**
16+
17+
```bash
18+
npm i
19+
```
20+
21+
**3. Run App**
22+
23+
```bash
24+
npm run dev
25+
```
26+
27+
## Contact
28+
29+
If you have any questions, feel free to reach out to me on [Twitter](https://twitter.com/mckaywrigley).

components/APIKeyInput.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
interface Props {
2+
apiKey: string;
3+
onChange: (apiKey: string) => void;
4+
}
5+
6+
export const APIKeyInput: React.FC<Props> = ({ apiKey, onChange }) => {
7+
return (
8+
<input
9+
className="mt-1 h-[24px] w-[280px] rounded-md border border-gray-300 px-3 py-2 text-black shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
10+
type="password"
11+
placeholder="OpenAI API Key"
12+
value={apiKey}
13+
onChange={(e) => onChange(e.target.value)}
14+
/>
15+
);
16+
};

components/CodeBlock.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { StreamLanguage } from '@codemirror/language';
2+
import { go } from '@codemirror/legacy-modes/mode/go';
3+
import { tokyoNight } from '@uiw/codemirror-theme-tokyo-night';
4+
import CodeMirror from '@uiw/react-codemirror';
5+
import { FC, useEffect, useState } from 'react';
6+
7+
interface Props {
8+
code: string;
9+
editable?: boolean;
10+
onChange?: (value: string) => void;
11+
}
12+
13+
export const CodeBlock: FC<Props> = ({
14+
code,
15+
editable = false,
16+
onChange = () => {},
17+
}) => {
18+
const [copyText, setCopyText] = useState<string>('Copy');
19+
20+
useEffect(() => {
21+
const timeout = setTimeout(() => {
22+
setCopyText('Copy');
23+
}, 2000);
24+
25+
return () => clearTimeout(timeout);
26+
}, [copyText]);
27+
28+
return (
29+
<div className="relative">
30+
<button
31+
className="absolute right-0 top-0 z-10 rounded bg-[#1A1B26] p-1 text-xs text-white hover:bg-[#2D2E3A] active:bg-[#2D2E3A]"
32+
onClick={() => {
33+
navigator.clipboard.writeText(code);
34+
setCopyText('Copied!');
35+
}}
36+
>
37+
{copyText}
38+
</button>
39+
40+
<CodeMirror
41+
editable={editable}
42+
value={code}
43+
minHeight="500px"
44+
extensions={[StreamLanguage.define(go)]}
45+
theme={tokyoNight}
46+
onChange={(value) => onChange(value)}
47+
/>
48+
</div>
49+
);
50+
};

components/LanguageSelect.tsx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import type { FC } from 'react';
2+
3+
interface Props {
4+
language: string;
5+
onChange: (language: string) => void;
6+
}
7+
8+
export const LanguageSelect: FC<Props> = ({ language, onChange }) => {
9+
const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
10+
onChange(e.target.value);
11+
};
12+
13+
return (
14+
<select
15+
className="w-full rounded-md bg-[#1F2937] px-4 py-2 text-neutral-200"
16+
value={language}
17+
onChange={handleChange}
18+
>
19+
{languages
20+
.sort((a, b) => a.label.localeCompare(b.label))
21+
.map((language) => (
22+
<option key={language.value} value={language.value}>
23+
{language.label}
24+
</option>
25+
))}
26+
</select>
27+
);
28+
};
29+
30+
const languages = [
31+
{ value: 'Pascal', label: 'Pascal' },
32+
{ value: 'JavaScript', label: 'JavaScript' },
33+
{ value: 'TypeScript', label: 'TypeScript' },
34+
{ value: 'Python', label: 'Python' },
35+
{ value: 'TSX', label: 'TSX' },
36+
{ value: 'JSX', label: 'JSX' },
37+
{ value: 'Vue', label: 'Vue' },
38+
{ value: 'Go', label: 'Go' },
39+
{ value: 'C', label: 'C' },
40+
{ value: 'C++', label: 'C++' },
41+
{ value: 'Java', label: 'Java' },
42+
{ value: 'C#', label: 'C#' },
43+
{ value: 'Visual Basic .NET', label: 'Visual Basic .NET' },
44+
{ value: 'SQL', label: 'SQL' },
45+
{ value: 'Assembly Language', label: 'Assembly Language' },
46+
{ value: 'PHP', label: 'PHP' },
47+
{ value: 'Ruby', label: 'Ruby' },
48+
{ value: 'Swift', label: 'Swift' },
49+
{ value: 'SwiftUI', label: 'SwiftUI' },
50+
{ value: 'Kotlin', label: 'Kotlin' },
51+
{ value: 'R', label: 'R' },
52+
{ value: 'Objective-C', label: 'Objective-C' },
53+
{ value: 'Perl', label: 'Perl' },
54+
{ value: 'SAS', label: 'SAS' },
55+
{ value: 'Scala', label: 'Scala' },
56+
{ value: 'Dart', label: 'Dart' },
57+
{ value: 'Rust', label: 'Rust' },
58+
{ value: 'Haskell', label: 'Haskell' },
59+
{ value: 'Lua', label: 'Lua' },
60+
{ value: 'Groovy', label: 'Groovy' },
61+
{ value: 'Elixir', label: 'Elixir' },
62+
{ value: 'Clojure', label: 'Clojure' },
63+
{ value: 'Lisp', label: 'Lisp' },
64+
{ value: 'Julia', label: 'Julia' },
65+
{ value: 'Matlab', label: 'Matlab' },
66+
{ value: 'Fortran', label: 'Fortran' },
67+
{ value: 'COBOL', label: 'COBOL' },
68+
{ value: 'Bash', label: 'Bash' },
69+
{ value: 'Powershell', label: 'Powershell' },
70+
{ value: 'PL/SQL', label: 'PL/SQL' },
71+
{ value: 'CSS', label: 'CSS' },
72+
{ value: 'Racket', label: 'Racket' },
73+
{ value: 'HTML', label: 'HTML' },
74+
{ value: 'NoSQL', label: 'NoSQL' },
75+
{ value: 'Natural Language', label: 'Natural Language' },
76+
{ value: 'CoffeeScript', label: 'CoffeeScript' },
77+
];

components/ModelSelect.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { OpenAIModel } from '@/types/types';
2+
import { FC } from 'react';
3+
4+
interface Props {
5+
model: OpenAIModel;
6+
onChange: (model: OpenAIModel) => void;
7+
}
8+
9+
export const ModelSelect: FC<Props> = ({ model, onChange }) => {
10+
const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
11+
onChange(e.target.value as OpenAIModel);
12+
};
13+
14+
return (
15+
<select
16+
className="h-[40px] w-[140px] rounded-md bg-[#1F2937] px-4 py-2 text-neutral-200"
17+
value={model}
18+
onChange={handleChange}
19+
>
20+
<option value="gpt-3.5-turbo">GPT-3.5</option>
21+
<option value="gpt-4">GPT-4</option>
22+
</select>
23+
);
24+
};

components/TextBlock.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
interface Props {
2+
text: string;
3+
editable?: boolean;
4+
onChange?: (value: string) => void;
5+
}
6+
7+
export const TextBlock: React.FC<Props> = ({
8+
text,
9+
editable = false,
10+
onChange = () => {},
11+
}) => {
12+
return (
13+
<textarea
14+
className="min-h-[500px] w-full bg-[#1A1B26] p-4 text-[15px] text-neutral-200 focus:outline-none"
15+
style={{ resize: 'none' }}
16+
value={text}
17+
onChange={(e) => onChange(e.target.value)}
18+
disabled={!editable}
19+
/>
20+
);
21+
};

0 commit comments

Comments
 (0)