Skip to content

Commit b52fb71

Browse files
committed
Project
1 parent 50cf554 commit b52fb71

6 files changed

Lines changed: 225 additions & 407 deletions

File tree

-73.6 KB
Binary file not shown.

Projects/ChatBot/images/user.png

-26.9 KB
Binary file not shown.

Projects/ChatBot/index.html

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
11
<!DOCTYPE html>
22
<html lang="en" dir="ltr">
33
<head>
4-
<meta charset="utf-8">
5-
<title>ChatGPT Clone</title>
6-
<link rel="stylesheet" href="style.css">
4+
<meta charset="UTF-8">
75
<meta name="viewport" content="width=device-width, initial-scale=1.0">
8-
<link rel="stylesheet"
9-
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
10-
<script src="script.js" defer></script>
6+
<title>JS Chatbot | CodeJunkie</title>
7+
<link rel="stylesheet" href="style.css">
8+
<link rel="icon" type="image/x-icon" href="./favicon_io/favicon-32x32.png">
9+
<!--Google fonts link for icons-->
10+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
11+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@48,400,1,0" />
1112
</head>
12-
13-
<body>
14-
<div class="chat-container"></div>
15-
<div class="typing-container">
16-
<div class="typing-content">
17-
<div class="typing-textarea">
18-
<textarea id="chat-input" spellcheck="false" placeholder="Enter a prompt here" required></textarea>
19-
<span id="send-btn" class="material-symbols-rounded">send</span>
20-
</div>
21-
<div class="typing-controls">
22-
<span id="theme-btn" class="material-symbols-rounded">light_mode</span>
23-
<span id="delete-btn" class="material-symbols-rounded">delete</span>
24-
</div>
13+
<body class="show-chatbot">
14+
<button class="chatbot-toggler">
15+
<span class="material-symbols-outlined">mode_comment</span>
16+
<span class="material-symbols-outlined">close</span>
17+
</button>
18+
<div class="chatbot">
19+
<header>
20+
<h2>Chatbot</h2>
21+
<span class="close-btn material-symbols-outlined">close</span>
22+
</header>
23+
<ul class = "chatbox">
24+
<li class = "chat incoming">
25+
<span class="material-symbols-outlined">smart_toy</span>
26+
<p>Hi there 👋🏼 <br> How may I help you?</p>
27+
</li>
28+
</ul>
29+
<div class="chat-input">
30+
<textarea placeholder="Enter a meesage..." spellcheck="false" required></textarea>
31+
<span id = "send-btn" class="material-symbols-rounded">send</span>
2532
</div>
26-
33+
</div>
34+
<script type="text/javascript" src="script.js"></script>
2735
</body>
28-
2936
</html>

Projects/ChatBot/script.js

Lines changed: 59 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,149 +1,86 @@
1-
const chatInput = document.querySelector("#chat-input");
2-
const sendButton = document.querySelector("#send-btn");
3-
const chatContainer = document.querySelector(".chat-container");
4-
const themeButton = document.querySelector("#theme-btn");
5-
const deleteButton = document.querySelector("#delete-btn");
6-
7-
let userText = null;
8-
const API_KEY = "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"; // Paste your API key here
9-
10-
const loadDataFromLocalstorage = () => {
11-
// Load saved chats and theme from local storage and apply/add on the page
12-
const themeColor = localStorage.getItem("themeColor");
13-
14-
document.body.classList.toggle("light-mode", themeColor === "light_mode");
15-
themeButton.innerText = document.body.classList.contains("light-mode") ? "dark_mode" : "light_mode";
16-
17-
const defaultText = `<div class="default-text">
18-
<h1>ChatGPT Clone</h1>
19-
<p>Start a conversation and explore the power of AI.<br> Your chat history will be displayed here.</p>
20-
</div>`
21-
22-
chatContainer.innerHTML = localStorage.getItem("all-chats") || defaultText;
23-
chatContainer.scrollTo(0, chatContainer.scrollHeight); // Scroll to bottom of the chat container
24-
}
25-
26-
const createChatElement = (content, className) => {
27-
// Create new div and apply chat, specified class and set html content of div
28-
const chatDiv = document.createElement("div");
29-
chatDiv.classList.add("chat", className);
30-
chatDiv.innerHTML = content;
31-
return chatDiv; // Return the created chat div
1+
const chatInput = document.querySelector(".chat-input textarea");
2+
const sendChatBtn = document.querySelector(".chat-input span");
3+
const chatbox = document.querySelector(".chatbox");
4+
const chatbotToggler = document.querySelector(".chatbot-toggler");
5+
const closeBtn = document.querySelector(".close-btn");
6+
7+
let userMessage = null; //variable to store user's message
8+
9+
const API_KEY = "PASTE YOUR API KEY"; //Paste your API key here....How to generate is explained in README.md
10+
const inputInitHeight = chatInput.scrollHeight;
11+
12+
const createChatLi = (message, className) => {
13+
//create a chat <li> element with passed message and className
14+
const chatLi = document.createElement("li");
15+
chatLi.classList.add("chat", `${className}`);
16+
let chatContent = className === "outgoing" ? `<p></p>` : `<span class="material-symbols-outlined">smart_toy</span><p></p>`;
17+
chatLi.innerHTML = chatContent;
18+
chatLi.querySelector("p").textContent = message;
19+
return chatLi; //return the chat <li> element
3220
}
3321

34-
const getChatResponse = async (incomingChatDiv) => {
35-
const API_URL = "https://api.openai.com/v1/completions";
36-
const pElement = document.createElement("p");
22+
const generateResponse = (chatElement) => {
23+
const API_URL = "https://api.openai.com/v1/chat/completions";
24+
const messageElement = chatElement.querySelector("p");
3725

38-
// Define the properties and data for the API request
26+
//define the properties and message for the api request
3927
const requestOptions = {
4028
method: "POST",
4129
headers: {
4230
"Content-Type": "application/json",
4331
"Authorization": `Bearer ${API_KEY}`
4432
},
4533
body: JSON.stringify({
46-
model: "text-davinci-003",
47-
prompt: userText,
48-
max_tokens: 2048,
49-
temperature: 0.2,
50-
n: 1,
51-
stop: null
34+
model: "gpt-3.5-turbo",
35+
messages: [{role: "user", content: userMessage}],
5236
})
5337
}
5438

55-
// Send POST request to API, get response and set the reponse as paragraph element text
56-
try {
57-
const response = await (await fetch(API_URL, requestOptions)).json();
58-
pElement.textContent = response.choices[0].text.trim();
59-
} catch (error) { // Add error class to the paragraph element and set error text
60-
pElement.classList.add("error");
61-
pElement.textContent = "Oops! Something went wrong while retrieving the response. Please try again.";
62-
}
63-
64-
// Remove the typing animation, append the paragraph element and save the chats to local storage
65-
incomingChatDiv.querySelector(".typing-animation").remove();
66-
incomingChatDiv.querySelector(".chat-details").appendChild(pElement);
67-
localStorage.setItem("all-chats", chatContainer.innerHTML);
68-
chatContainer.scrollTo(0, chatContainer.scrollHeight);
69-
}
70-
71-
const copyResponse = (copyBtn) => {
72-
// Copy the text content of the response to the clipboard
73-
const reponseTextElement = copyBtn.parentElement.querySelector("p");
74-
navigator.clipboard.writeText(reponseTextElement.textContent);
75-
copyBtn.textContent = "done";
76-
setTimeout(() => copyBtn.textContent = "content_copy", 1000);
77-
}
78-
79-
const showTypingAnimation = () => {
80-
// Display the typing animation and call the getChatResponse function
81-
const html = `<div class="chat-content">
82-
<div class="chat-details">
83-
<img src="images/chatbot.png" alt="chatbot-img">
84-
<div class="typing-animation">
85-
<div class="typing-dot" style="--delay: 0.2s"></div>
86-
<div class="typing-dot" style="--delay: 0.3s"></div>
87-
<div class="typing-dot" style="--delay: 0.4s"></div>
88-
</div>
89-
</div>
90-
<span onclick="copyResponse(this)" class="material-symbols-rounded">content_copy</span>
91-
</div>`;
92-
// Create an incoming chat div with typing animation and append it to chat container
93-
const incomingChatDiv = createChatElement(html, "incoming");
94-
chatContainer.appendChild(incomingChatDiv);
95-
chatContainer.scrollTo(0, chatContainer.scrollHeight);
96-
getChatResponse(incomingChatDiv);
39+
//send POST request to API, get response
40+
fetch(API_URL, requestOptions).then(res => res.json()).then(data => {
41+
messageElement.textContent = data.choices[0].message.content.trim();
42+
}).catch(() => {
43+
messageElement.classList.add("error");
44+
messageElement.textContent = "Oops! Something went wrong. Please try again.";
45+
}).finally(() => chatbox.scrollTo(0, chatbox.scrollHeight));
9746
}
9847

99-
const handleOutgoingChat = () => {
100-
userText = chatInput.value.trim();
101-
if (!userText) return;
48+
const handleChat = () => {
49+
userMessage = chatInput.value.trim(); //Get user enetred message and remove extra whitespace
50+
if(!userMessage) return;
10251

52+
//clear the input textarea and set its height to default
10353
chatInput.value = "";
104-
chatInput.style.height = `${initialInputHeight}px`;
105-
106-
const html = `<div class="chat-content">
107-
<div class="chat-details">
108-
<img src="images/user.png" alt="user-img">
109-
<p>${userText}</p>
110-
</div>
111-
</div>`;
112-
113-
const outgoingChatDiv = createChatElement(html, "outgoing");
114-
chatContainer.querySelector(".default-text")?.remove();
115-
chatContainer.appendChild(outgoingChatDiv);
116-
chatContainer.scrollTo(0, chatContainer.scrollHeight);
117-
setTimeout(showTypingAnimation, 500);
54+
chatInput.style.height = `${inputInitHeight}px`; //resetting the textarea height to its default height once a message is sent
55+
56+
//append the user's message to the chatbox
57+
chatbox.appendChild(createChatLi(userMessage, "outgoing"));
58+
chatbox.scrollTo(0, chatbox.scrollHeight);
59+
60+
setTimeout(() => {
61+
//Display "Thinking..." message while waiting for the response
62+
const incomingChatLi = createChatLi("Thinking...", "incoming");
63+
chatbox.appendChild(incomingChatLi);
64+
chatbox.scrollTo(0, chatbox.scrollHeight);
65+
generateResponse(incomingChatLi);
66+
},600);
11867
}
119-
120-
deleteButton.addEventListener("click", () => {
121-
if (confirm("Are you sure you want to delete all the chats?")) {
122-
localStorage.removeItem("all-chats");
123-
loadDataFromLocalstorage();
124-
}
125-
});
126-
127-
themeButton.addEventListener("click", () => {
128-
document.body.classList.toggle("light-mode");
129-
localStorage.setItem("themeColor", themeButton.innerText);
130-
themeButton.innerText = document.body.classList.contains("light-mode") ? "dark_mode" : "light_mode";
131-
});
132-
133-
const initialInputHeight = chatInput.scrollHeight;
134-
13568
chatInput.addEventListener("input", () => {
136-
chatInput.style.height = `${initialInputHeight}px`;
69+
//Adjust the height of the input textarea based on its content
70+
chatInput.style.height = `${inputInitHeight}px`;
13771
chatInput.style.height = `${chatInput.scrollHeight}px`;
13872
});
13973

14074
chatInput.addEventListener("keydown", (e) => {
141-
142-
if (e.key === "Enter" && !e.shiftKey && window.innerWidth > 800) {
75+
//if enter key is pressed without shift key and the window
76+
//width is greater than the 800px, handle the chat
77+
if(e.key === "Enter" && !e.shiftKey && window.innerWidth > 800) {
14378
e.preventDefault();
144-
handleOutgoingChat();
79+
handleChat();
14580
}
14681
});
14782

148-
loadDataFromLocalstorage();
149-
sendButton.addEventListener("click", handleOutgoingChat);
83+
sendChatBtn.addEventListener("click", handleChat);
84+
closeBtn.addEventListener("click", ()=> document.body.classList.remove("show-chatbot"));
85+
chatbotToggler.addEventListener("click", ()=> document.body.classList.toggle("show-chatbot"));
86+

0 commit comments

Comments
 (0)