├── .gitignore
├── api
├── package.json
└── server.js
└── client
├── .gitignore
├── index.html
├── package.json
├── public
└── favicon.ico
├── src
├── App.jsx
├── assets
│ ├── bot.png
│ ├── loader.svg
│ ├── send.svg
│ └── user.png
├── index.css
└── main.jsx
└── vite.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package-lock.json
3 | .env
--------------------------------------------------------------------------------
/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "codex-server",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "server": "nodemon server"
8 | },
9 | "dependencies": {
10 | "cors": "^2.8.5",
11 | "dotenv": "^16.0.3",
12 | "express": "^4.18.2",
13 | "nodemon": "^2.0.20",
14 | "openai": "^3.1.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/api/server.js:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import cors from "cors";
3 | import * as dotenv from "dotenv";
4 | import { Configuration, OpenAIApi } from "openai";
5 |
6 | dotenv.config();
7 |
8 | const app = express();
9 | app.use(cors());
10 | app.use(express.json());
11 |
12 | app.get("/", async (req, res) => {
13 | res.status(200).send({
14 | message:
15 | "This is ChatGPT AI APP server url, please visit https://chatgpt-ai-app-od21.onrender.com",
16 | });
17 | });
18 |
19 | const configuration = new Configuration({
20 | apiKey: process.env.OPENAI_API_KEY,
21 | });
22 | const openai = new OpenAIApi(configuration);
23 |
24 | app.post("/", async (req, res) => {
25 | try {
26 | const response = await openai.createCompletion({
27 | model: "text-davinci-003",
28 | prompt: req.body.input,
29 | temperature: 0,
30 | max_tokens: 4000,
31 | top_p: 1,
32 | frequency_penalty: 0.5,
33 | presence_penalty: 0,
34 | });
35 | console.log("PASSED: ", req.body.input);
36 |
37 | res.status(200).send({
38 | bot: response.data.choices[0].text,
39 | });
40 | } catch (error) {
41 | console.log("FAILED:", req.body.input);
42 | console.error(error);
43 | res.status(500).send(error);
44 | }
45 | });
46 |
47 | app.listen(4000, () => console.log("Server is running on port 4000"));
48 |
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ChatGPT AI APP
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "client",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "axios": "^1.2.1",
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0",
15 | "react-icons": "^4.7.1",
16 | "sass": "^1.57.1"
17 | },
18 | "devDependencies": {
19 | "@types/react": "^18.0.26",
20 | "@types/react-dom": "^18.0.9",
21 | "@vitejs/plugin-react": "^3.0.0",
22 | "vite": "^4.0.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShariqAnsari88/chatgpt-ai-app/c04ea2ad8dbfb21160745a02c5e14451481fc51c/client/public/favicon.ico
--------------------------------------------------------------------------------
/client/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 | import axios from "axios";
3 |
4 | import send from "./assets/send.svg";
5 | import user from "./assets/user.png";
6 | import bot from "./assets/bot.png";
7 | import loadingIcon from "./assets/loader.svg";
8 |
9 | function App() {
10 | const [input, setInput] = useState("");
11 | const [posts, setPosts] = useState([]);
12 |
13 | useEffect(() => {
14 | document.querySelector(".layout").scrollTop =
15 | document.querySelector(".layout").scrollHeight;
16 | }, [posts]);
17 |
18 | const fetchBotResponse = async () => {
19 | const { data } = await axios.post(
20 | "https://chatgpt-ai-app-od21.onrender.com",
21 | // "http://localhost:5173",
22 | { input },
23 | {
24 | headers: {
25 | "Content-Type": "application/json",
26 | },
27 | }
28 | );
29 | return data;
30 | };
31 |
32 | const autoTypingBotResponse = (text) => {
33 | let index = 0;
34 | let interval = setInterval(() => {
35 | if (index < text.length) {
36 | setPosts((prevState) => {
37 | let lastItem = prevState.pop();
38 | if (lastItem.type !== "bot") {
39 | prevState.push({
40 | type: "bot",
41 | post: text.charAt(index - 1),
42 | });
43 | } else {
44 | prevState.push({
45 | type: "bot",
46 | post: lastItem.post + text.charAt(index - 1),
47 | });
48 | }
49 | return [...prevState];
50 | });
51 | index++;
52 | } else {
53 | clearInterval(interval);
54 | }
55 | }, 20);
56 | };
57 |
58 | const onSubmit = () => {
59 | if (input.trim() === "") return;
60 | updatePosts(input);
61 | updatePosts("loading...", false, true);
62 | setInput("");
63 | fetchBotResponse().then((res) => {
64 | console.log(res.bot.trim());
65 | updatePosts(res.bot.trim(), true);
66 | });
67 | };
68 |
69 | const updatePosts = (post, isBot, isLoading) => {
70 | if (isBot) {
71 | autoTypingBotResponse(post);
72 | } else {
73 | setPosts((prevState) => {
74 | return [
75 | ...prevState,
76 | {
77 | type: isLoading ? "loading" : "user",
78 | post,
79 | },
80 | ];
81 | });
82 | }
83 | };
84 |
85 | const onKeyUp = (e) => {
86 | if (e.key === "Enter" || e.which === 13) {
87 | onSubmit();
88 | }
89 | };
90 |
91 | return (
92 |
93 |
94 |
95 | {posts.map((post, index) => (
96 |
104 |
105 |

113 |
114 | {post.type === "loading" ? (
115 |
116 |

117 |
118 | ) : (
119 |
{post.post}
120 | )}
121 |
122 | ))}
123 |
124 |
125 |
139 |
140 | );
141 | }
142 |
143 | export default App;
144 |
--------------------------------------------------------------------------------
/client/src/assets/bot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShariqAnsari88/chatgpt-ai-app/c04ea2ad8dbfb21160745a02c5e14451481fc51c/client/src/assets/bot.png
--------------------------------------------------------------------------------
/client/src/assets/loader.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/src/assets/send.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/client/src/assets/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ShariqAnsari88/chatgpt-ai-app/c04ea2ad8dbfb21160745a02c5e14451481fc51c/client/src/assets/user.png
--------------------------------------------------------------------------------
/client/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
3 | font-size: 16px;
4 | line-height: 24px;
5 | font-weight: 400;
6 |
7 | color-scheme: light dark;
8 | color: rgba(255, 255, 255, 0.87);
9 | background-color: #1c1c25;
10 |
11 | font-synthesis: none;
12 | text-rendering: optimizeLegibility;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | -webkit-text-size-adjust: 100%;
16 | }
17 |
18 | * {
19 | margin: 0;
20 | padding: 0;
21 | box-sizing: border-box;
22 | }
23 |
24 | .chatGPT-app {
25 | max-width: 1200px;
26 | margin: 0 auto;
27 | padding: 0 20px;
28 | }
29 |
30 | footer {
31 | display: flex;
32 | justify-content: space-between;
33 | align-items: center;
34 | padding: 14px 10px;
35 | padding-right: 5px;
36 | gap: 10px;
37 | width: 100%;
38 | height: 50px;
39 | background: #2b2b36;
40 | border-radius: 10000px;
41 | }
42 | .composebar {
43 | padding: 0 10px;
44 | font-weight: 400;
45 | font-size: 16px;
46 | line-height: 30px;
47 | color: #ffffff;
48 | outline: 0;
49 | border: 0;
50 | max-width: calc(100% - 120px);
51 | min-width: calc(100% - 120px);
52 | background-color: transparent;
53 | }
54 | .send-button {
55 | display: flex;
56 | justify-content: center;
57 | align-items: center;
58 | padding: 15px 25px;
59 | height: 40px;
60 | background: linear-gradient(269deg, #2541fc 1.77%, #5466f2 99.15%);
61 | border-radius: 47px;
62 | cursor: pointer;
63 | }
64 | .send-button img {
65 | width: 20px;
66 | margin-right: -5px;
67 | }
68 | .chat-container {
69 | height: calc(100vh - 80px);
70 | padding: 20px 0;
71 | }
72 | .layout {
73 | width: 100%;
74 | height: 100%;
75 | overflow: auto;
76 | display: flex;
77 | flex-direction: column;
78 | gap: 30px;
79 | scrollbar-width: none;
80 | }
81 | .chat-bubble {
82 | display: flex;
83 | gap: 15px;
84 | }
85 | .chat-bubble .avatar {
86 | width: 44px;
87 | height: 44px;
88 | border-radius: 50%;
89 | background: #d9d9d9;
90 | display: flex;
91 | align-items: center;
92 | justify-content: center;
93 | flex-shrink: 0;
94 | }
95 | .chat-bubble.bot .avatar {
96 | background: linear-gradient(269deg, #2541fc 1.77%, #5466f2 99.15%);
97 | }
98 | .chat-bubble .avatar img {
99 | width: 22px;
100 | }
101 | .post {
102 | padding: 10px 20px;
103 | width: fit-content;
104 | max-width: 100%;
105 | min-height: 40px;
106 | background: #2b2b36;
107 | border-radius: 22px;
108 | white-space: pre-wrap;
109 | }
110 | .chat-bubble.bot .post {
111 | background: #21212c;
112 | }
113 | .loader {
114 | padding: 0 20px;
115 | width: fit-content;
116 | max-width: 100%;
117 | min-height: 40px;
118 | background: #2b2b36;
119 | border-radius: 22px;
120 | display: flex;
121 | align-items: center;
122 | }
123 |
--------------------------------------------------------------------------------
/client/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 | import "./index.css";
5 |
6 | ReactDOM.createRoot(document.getElementById("root")).render();
7 |
--------------------------------------------------------------------------------
/client/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------