Skip to content

Commit cf905eb

Browse files
authored
Fixes #343 (#389)
1 parent 65df1b8 commit cf905eb

File tree

5 files changed

+359
-1
lines changed

5 files changed

+359
-1
lines changed

chatbox.css

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap');
2+
3+
4+
5+
.chatbot-toggler {
6+
position: fixed;
7+
bottom: 90px;
8+
z-index: 2;
9+
right: 35px;
10+
outline: none;
11+
border: none;
12+
height: 50px;
13+
width: 50px;
14+
display: flex;
15+
cursor: pointer;
16+
align-items: center;
17+
justify-content: center;
18+
border-radius: 50%;
19+
background: #333;
20+
transition: all 0.2s ease;
21+
}
22+
body.show-chatbot .chatbot-toggler {
23+
transform: rotate(90deg);
24+
}
25+
.chatbot-toggler span {
26+
color: #fff;
27+
position: absolute;
28+
}
29+
.chatbot-toggler span:last-child,
30+
body.show-chatbot .chatbot-toggler span:first-child {
31+
opacity: 0;
32+
}
33+
body.show-chatbot .chatbot-toggler span:last-child {
34+
opacity: 1;
35+
}
36+
.chatbot {
37+
position: fixed;
38+
right: 35px;
39+
bottom: 150px;
40+
z-index: 2;
41+
width: 500px;
42+
height: 400px;
43+
background: #fff;
44+
border-radius: 15px;
45+
overflow: hidden;
46+
opacity: 0;
47+
pointer-events: none;
48+
transform: scale(0.5);
49+
transform-origin: bottom right;
50+
box-shadow: 0 0 128px 0 rgba(0,0,0,0.1),
51+
0 32px 64px -48px rgba(0,0,0,0.5);
52+
transition: all 0.1s ease;
53+
}
54+
body.show-chatbot .chatbot {
55+
opacity: 1;
56+
pointer-events: auto;
57+
transform: scale(1);
58+
}
59+
.chatbot header {
60+
padding: 16px 0;
61+
position: relative;
62+
text-align: center;
63+
color: #fff;
64+
background: #333;
65+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
66+
}
67+
.chatbot header span {
68+
position: absolute;
69+
right: 15px;
70+
top: 50%;
71+
display: none;
72+
cursor: pointer;
73+
transform: translateY(-50%);
74+
}
75+
header h2 {
76+
font-size: 1.4rem;
77+
}
78+
.chatbot .chatbox {
79+
overflow-y: auto;
80+
height: 350px;
81+
padding: 30px 20px 100px;
82+
}
83+
.chatbot :where(.chatbox, textarea)::-webkit-scrollbar {
84+
width: 6px;
85+
}
86+
.chatbot :where(.chatbox, textarea)::-webkit-scrollbar-track {
87+
background: #fff;
88+
border-radius: 25px;
89+
}
90+
.chatbot :where(.chatbox, textarea)::-webkit-scrollbar-thumb {
91+
background: #ccc;
92+
border-radius: 25px;
93+
}
94+
.chatbox .chat {
95+
display: flex;
96+
list-style: none;
97+
}
98+
.chatbox .outgoing {
99+
margin: 20px 0;
100+
justify-content: flex-end;
101+
}
102+
.chatbox .incoming span {
103+
width: 32px;
104+
height: 32px;
105+
color: #fff;
106+
cursor: default;
107+
text-align: center;
108+
line-height: 32px;
109+
align-self: flex-end;
110+
background: #333;
111+
border-radius: 4px;
112+
margin: 0 10px 7px 0;
113+
}
114+
.chatbox .chat p {
115+
white-space: pre-wrap;
116+
padding: 12px 16px;
117+
border-radius: 10px 10px 0 10px;
118+
max-width: 75%;
119+
margin-bottom: 10px;
120+
margin-left: 5px;
121+
color: #fff;
122+
font-size: 0.95rem;
123+
background: #333;
124+
}
125+
.chatbox .incoming p {
126+
border-radius: 10px 10px 10px 0;
127+
}
128+
.chatbox .chat p.error {
129+
color: #721c24;
130+
background: #f8d7da;
131+
}
132+
.chatbox .incoming p {
133+
color: #000;
134+
background: #f2f2f2;
135+
}
136+
.chatbot .chat-input {
137+
display: flex;
138+
gap: 5px;
139+
position: absolute;
140+
bottom: 0;
141+
width: 100%;
142+
background: #fff;
143+
padding: 3px 20px;
144+
border-top: 1px solid #ddd;
145+
}
146+
.chat-input textarea {
147+
height: 55px;
148+
width: 100%;
149+
border: none;
150+
outline: none;
151+
resize: none;
152+
max-height: 180px;
153+
padding: 15px 15px 15px 0;
154+
font-size: 0.95rem;
155+
}
156+
.chat-input span {
157+
align-self: flex-end;
158+
color:#333;
159+
cursor: pointer;
160+
height: 55px;
161+
display: flex;
162+
align-items: center;
163+
visibility: hidden;
164+
font-size: 1.35rem;
165+
}
166+
.chat-input textarea:valid ~ span {
167+
visibility: visible;
168+
}
169+
.hero img{
170+
z-index: -1;
171+
}
172+
173+
@media (max-width: 490px) {
174+
.chatbot-toggler {
175+
right: 35px;
176+
bottom: 90px;
177+
z-index: 3;
178+
}
179+
.chatbot {
180+
right: 0;
181+
bottom: 0;
182+
height: 100%;
183+
border-radius: 0;
184+
width: 100%;
185+
z-index: 4;
186+
}
187+
.chatbot .chatbox {
188+
height: 90%;
189+
padding: 25px 15px 100px;
190+
}
191+
.chatbot .chat-input {
192+
padding: 5px 15px;
193+
}
194+
.chatbot header span {
195+
display: block;
196+
}
197+
}

chatbox.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
const chatbotToggler = document.querySelector(".chatbot-toggler");
2+
const closeBtn = document.querySelector(".close-btn");
3+
const chatbox = document.querySelector(".chatbox");
4+
const chatInput = document.querySelector(".chat-input textarea");
5+
const sendChatBtn = document.querySelector(".chat-input span");
6+
7+
let userMessage = null; // Variable to store user's message
8+
const API_KEY = "PASTE-YOUR-API-KEY"; // Paste your API key here
9+
const inputInitHeight = chatInput.scrollHeight;
10+
11+
const predefinedAnswers = {
12+
"What is CSEdge?": "CSEdge is an online internship platform that provides students with the opportunity to gain practical experience in the field of software development. We offer a variety of internship programs designed to help students develop their skills and enhance their employability.",
13+
"What kind of internship programs does CSEdge offer?": "CSEdge offers a variety of internship programs focused on software development. Our programs are designed to provide practical experience and skill development in various areas of software engineering.",
14+
"Why should I choose CSEdge for my internship?": "CSEdge internships are designed to help students gain practical experience and develop their skills in software development. We are MSME registered and our programs are AICTE approved, ensuring top-notch quality and relevance.",
15+
"Are CSEdge internship programs AICTE approved?": "Yes, our internship programs are AICTE approved, ensuring top-notch quality and relevance.",
16+
"Is CSEdge MSME registered?": "Yes, CSEdge is MSME registered, emphasizing our commitment to quality and continuous learning.",
17+
"How can I apply for an internship at CSEdge?": "You can apply for an internship at CSEdge by visiting our website and navigating to the internship programs section. Follow the instructions provided to submit your application.",
18+
"What are the benefits of doing an internship at CSEdge?": "Internships at CSEdge provide practical experience in software development, helping you develop your skills and enhance your employability. Our programs are AICTE approved, ensuring they meet high standards of quality.",
19+
"How long are the internship programs at CSEdge?": "The duration of our internship programs varies depending on the specific program. Please visit our website for detailed information on each program's duration.",
20+
"Is there any fee to join the internship programs at CSEdge?": "For detailed information about the fees associated with our internship programs, please visit our website or contact our support team.",
21+
"Can international students apply for internships at CSEdge?": "Yes, international students are welcome to apply for our internship programs. Please check the specific program details for any additional requirements."
22+
};
23+
24+
25+
const createChatLi = (message, className) => {
26+
// Create a chat <li> element with passed message and className
27+
const chatLi = document.createElement("li");
28+
chatLi.classList.add("chat", `${className}`);
29+
let chatContent = className === "outgoing" ? `<p></p>` : `<span class="material-symbols-outlined">smart_toy</span><p></p>`;
30+
chatLi.innerHTML = chatContent;
31+
chatLi.querySelector("p").textContent = message;
32+
if (className === "question") {
33+
chatLi.style.cursor = "pointer";
34+
}
35+
return chatLi; // return chat <li> element
36+
}
37+
38+
39+
const generateResponse = (chatElement) => {
40+
const API_URL = "https://api.openai.com/v1/chat/completions";
41+
const messageElement = chatElement.querySelector("p");
42+
43+
// Define the properties and message for the API request
44+
const requestOptions = {
45+
method: "POST",
46+
headers: {
47+
"Content-Type": "application/json",
48+
"Authorization": `Bearer ${API_KEY}`
49+
},
50+
body: JSON.stringify({
51+
model: "gpt-3.5-turbo",
52+
messages: [{role: "user", content: userMessage}],
53+
})
54+
}
55+
56+
// Send POST request to API, get response and set the reponse as paragraph text
57+
fetch(API_URL, requestOptions).then(res => res.json()).then(data => {
58+
messageElement.textContent = data.choices[0].message.content.trim();
59+
}).catch(() => {
60+
messageElement.classList.add("error");
61+
messageElement.textContent = "Oops! Something went wrong. Please try again.";
62+
}).finally(() => chatbox.scrollTo(0, chatbox.scrollHeight));
63+
}
64+
65+
const handleChat = () => {
66+
userMessage = chatInput.value.trim(); // Get user entered message and remove extra whitespace
67+
if (!userMessage) return;
68+
69+
// Clear the input textarea and set its height to default
70+
chatInput.value = "";
71+
chatInput.style.height = `${inputInitHeight}px`;
72+
73+
// Append the user's message to the chatbox
74+
chatbox.appendChild(createChatLi(userMessage, "outgoing"));
75+
chatbox.scrollTo(0, chatbox.scrollHeight);
76+
77+
// Check if the message matches a predefined question
78+
if (userMessage == "Hi" || userMessage == "hi" || userMessage == "HI")
79+
showQuestionList();
80+
else {
81+
setTimeout(() => {
82+
// Display "Thinking..." message while waiting for the response
83+
const incomingChatLi = createChatLi("Thinking...", "incoming");
84+
chatbox.appendChild(incomingChatLi);
85+
chatbox.scrollTo(0, chatbox.scrollHeight);
86+
generateResponse(incomingChatLi);
87+
}, 600);
88+
}
89+
}
90+
91+
chatInput.addEventListener("input", () => {
92+
// Adjust the height of the input textarea based on its content
93+
chatInput.style.height = `${inputInitHeight}px`;
94+
chatInput.style.height = `${chatInput.scrollHeight}px`;
95+
});
96+
97+
chatInput.addEventListener("keydown", (e) => {
98+
// If Enter key is pressed without Shift key and the window
99+
// width is greater than 800px, handle the chat
100+
if (e.key === "Enter" && !e.shiftKey && window.innerWidth > 800) {
101+
e.preventDefault();
102+
handleChat();
103+
}
104+
});
105+
106+
sendChatBtn.addEventListener("click", handleChat);
107+
closeBtn.addEventListener("click", () => document.body.classList.remove("show-chatbot"));
108+
chatbotToggler.addEventListener("click", () => document.body.classList.toggle("show-chatbot"));
109+
110+
function showWelcomeMessage() {
111+
const welcomeChatLi = createChatLi("Hi! Welcome to CSEdge Chatbot. Say Hi to display menu.");
112+
chatbox.appendChild(welcomeChatLi);
113+
chatbox.scrollTo(0, chatbox.scrollHeight);
114+
}
115+
116+
// Function to display list of questions
117+
function showQuestionList() {
118+
for (const question in predefinedAnswers) {
119+
const questionChatLi = createChatLi(question, "question");
120+
questionChatLi.addEventListener("click", () => showAnswer(question));
121+
questionChatLi.style.cursor = "pointer";
122+
chatbox.appendChild(questionChatLi);
123+
}
124+
chatbox.scrollTo(0, chatbox.scrollHeight);
125+
}
126+
127+
// Function to display answer based on clicked question
128+
function showAnswer(clickedQuestion) {
129+
const answer = predefinedAnswers[clickedQuestion];
130+
const answerChatLi = createChatLi(answer, "incoming");
131+
chatbox.appendChild(answerChatLi);
132+
chatbox.scrollTo(0, chatbox.scrollHeight);
133+
}
134+
135+
// Call showWelcomeMessage and showQuestionList initially
136+
showWelcomeMessage();
137+
138+

home.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ body.dark-mode .section-heading{
295295
display: flex;
296296
flex-wrap: wrap;
297297
justify-content: center;
298+
z-index: 1;
298299
}
299300

300301
.internship-program li {

home.html

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
<link rel="apple-touch-icon" sizes="180x180" href="/Images/CSEDGE-LOGO32X32.png">
1919
<link rel="icon" href="./Images/CSEDGE-LOGO32X32.png" type="image/png" sizes="32x32">
2020
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css">
21+
<!--chatbox-->
22+
<link rel="stylesheet" href="chatbox.css">
23+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" />
24+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@48,400,1,0" />
25+
<script src="chatbox.js" defer></script>
2126

2227
<!-- AOS.js -->
2328
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
@@ -85,6 +90,23 @@ <h2>Unlock your<br> potential<br> with CSEdge </h2>
8590
</div>
8691
<img src="./Images/HomeImage.png" style="scale: 1.0;" alt="ARTWORK">
8792
</section>
93+
<button class="chatbot-toggler">
94+
<span class="material-symbols-rounded">mode_comment</span>
95+
<span class="material-symbols-outlined">close</span>
96+
</button>
97+
<div class="chatbot">
98+
<header>
99+
<h2>Chatbot</h2>
100+
<span class="close-btn material-symbols-outlined">close</span>
101+
</header>
102+
<ul class="chatbox">
103+
104+
</ul>
105+
<div class="chat-input">
106+
<textarea placeholder="Enter a message..." spellcheck="false" required></textarea>
107+
<span id="send-btn" class="material-symbols-rounded">send</span>
108+
</div>
109+
</div>
88110
<!--About Section-->
89111
<section id="AboutUS">
90112
<h2 class="section-heading" data-aos="fade-up">ABOUT US</h2>

navbar.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ nav ul li a:hover::after {
201201
position: fixed;
202202
bottom: 20px;
203203
right: 30px;
204-
z-index: 99;
204+
z-index: 1;
205205
border: none;
206206
outline: none;
207207
background-color: #555;

0 commit comments

Comments
 (0)