Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Fixes Chatbot on homepage #906

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions website/chatbot.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap');
.chatbot__button {
position: fixed;
bottom: 15px;
right: 30px;
width: 60px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
background: #3b8fdd;
color: #f3f6f8;
border: none;
border-radius: 60%;
outline: none;
cursor: pointer;
}

.chatbot__button span {
position: absolute;
}

.show-chatbot .chatbot__button span:first-child,
.chatbot__button span:last-child {
opacity: 0;
}

.show-chatbot .chatbot__button span:last-child {
opacity: 1;
}

.chatbot {
position: fixed;
bottom: 80px;
right: 35px;
width: 425px;
background-color: #f3f7f8;
border-radius: 15px;
box-shadow: 0 0 128px 0 rgba(168, 232, 248, 0.5) 0 32px 64px -48px rgba(7, 153, 7, 0.5);
transform: scale(0.5);
transition: transform 0.3s ease;
overflow: hidden;
opacity: 0;
pointer-events: none;
}

.show-chatbot .chatbot {
opacity: 1;
pointer-events: auto;
transform: scale(1);
}

.chatbot__header {
position: relative;
background-color: rgb(73, 169, 230);
text-align: center;
padding: 16px 0;
}

.chatbot__header span {
display: none;
position: absolute;
top: 40%;
right: 20px;
color: lightskyblue;
transform: translateY(-50%);
cursor: pointer;
}

.chatbox__title {
font-size: 1.4rem;
color: #f3f7f8;
}

.chatbot__box {
height: 350px;
overflow-y: auto;
padding: 30px 20px 100px;
background-repeat: no-repeat;
background-size: cover;
filter: brightness(1);
}

.chatbot__chat {
display: flex;
}

.chatbot__chat p {
max-width: 75%;
font-size: 0.95rem;
white-space: pre-wrap;
color: white;
background-color: #019ef9;
border-radius: 10px 10px 0 10px;
padding: 12px 16px;
}

.chatbot__chat p.error {
color: #721c24;
background: #f8d7da;
}

.incoming p {
color: #202020;
background: #bdc3c7;
width: 150px;
border-radius: 10px 0px 10px 0px;
}

.incoming span {
width: 32px;
height: 32px;
line-height: 32px;
color: #f3f7f8;
background-color: #227ebb;
border-radius: 4px;
text-align: center;
align-self: flex-end;
margin: 0 10px 7px 0;
}

.outgoing {
justify-content: flex-end;
margin: 20px 0;
}

.incoming {
margin: 20px 0;
}

.chatbot__input-box {
position: absolute;
bottom: 0;
width: 90%;
display: flex;
gap: 5px;
align-items: center;
border-top: 1px solid #227ebb;
background: rgb(73, 169, 230);
padding: 5px 20px;
}

.chatbot__textarea {
width: 80%;
min-height: 0px;
max-height: 50px;
font-size: 0.95rem;
padding: 16px 15px 16px 0;
color: #202020;
border: none;
outline: none;
resize: none;
background: transparent;
}

.chatbot__textarea::placeholder {
font-family: 'Poppins', sans-serif;
color: #fff;
}

.chatbot__input-box span {
font-size: 1.75rem;
color: white;
cursor: pointer;
visibility: hidden;
}

.chatbot__textarea:valid~span {
visibility: visible;
}

@media (max-width: 490px) {
.chatbot {
right: 0;
bottom: 0;
width: 100%;
height: 100%;
border-radius: 0;
}
.chatbot__box {
height: 90%;
}
.chatbot__header span {
display: inline;
}
}
86 changes: 86 additions & 0 deletions website/chatbot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const chatbotToggle = document.querySelector('.chatbot__button');
const sendChatBtn = document.querySelector('.chatbot__input-box span');
const chatInput = document.querySelector('.chatbot__textarea');
const chatBox = document.querySelector('.chatbot__box');
const chatbotCloseBtn = document.querySelector('.chatbot__header span');

let userMessage;
// Need GPT key
const inputInitHeight = chatInput.scrollHeight;
const API_KEY = '033f3bcc57msh4cbeceaaa74b3fbp172fd5jsn8008c32db481'; // ~IMPORTANT~

const createChatLi = (message, className) => {
const chatLi = document.createElement('li');
chatLi.classList.add('chatbot__chat', className);
chatLi.innerHTML = `<p>${message}</p>`;
return chatLi;
};

const generateResponse = (incomingChatLi) => {
const API_URL = 'https://chatgpt53.p.rapidapi.com/';
const messageElement = incomingChatLi.querySelector('p');

const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-RapidAPI-Key": "033f3bcc57msh4cbeceaaa74b3fbp172fd5jsn8008c32db481", // ! IMPORTANT !
"X-RapidAPI-Host": "chatgpt53.p.rapidapi.com",
},
body: JSON.stringify({
messages: [{ role: "user", content: userMessage }],
}),
};

console.log('Sending API request:', requestOptions);

fetch(API_URL, requestOptions)
.then((res) => res.json())
.then((data) => {
console.log('API response:', data);
console.log(data.choices[0].message.content);
messageElement.textContent = data.choices[0].message.content;
})
.catch((error) => {
console.log('API error:', error);
messageElement.classList.add('error');
messageElement.textContent = 'Oops! Please try again!';
})
.finally(() => chatBox.scrollTo(0, chatBox.scrollHeight));
};


const handleChat = () => {
userMessage = chatInput.value.trim();
if (!userMessage) return;
chatInput.value = '';
chatInput.style.height = `${inputInitHeight}px`;

chatBox.appendChild(createChatLi(userMessage, 'outgoing'));
chatBox.scrollTo(0, chatBox.scrollHeight);

setTimeout(() => {
const incomingChatLi = createChatLi('Typing...', 'incoming');
chatBox.appendChild(incomingChatLi);
chatBox.scrollTo(0, chatBox.scrollHeight);
generateResponse(incomingChatLi);
}, 600);
};

chatInput.addEventListener('input', () => {
chatInput.style.height = `${inputInitHeight}px`;
chatInput.style.height = `${chatInput.scrollHeight}px`;
});
chatInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.shiftKey && window.innerWidth > 800) {
e.preventDefault();
handleChat();
}
});
chatbotToggle.addEventListener('click', () =>
document.body.classList.toggle('show-chatbot')
);
chatbotCloseBtn.addEventListener('click', () =>
document.body.classList.remove('show-chatbot')
);
sendChatBtn.addEventListener('click', handleChat);
67 changes: 67 additions & 0 deletions website/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,73 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/x-icon" href="assets/logo.png">
<title>ResourceHub</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="chatbot.css">
<style>
.search-container {
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
background-color: white;
/* box-shadow: 0 4px 4px rgba(0, 0, 0, 0.1); */
}

.search-input {
width: 80%;
max-width: 600px;
padding: 15px;
font-size: 18px;
border: 1px solid #ddd;
border-radius: 25px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}

.search-input:focus {
outline: none;
border-color: #aaa;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
</style>
</head>

<body>
<h1 id="main-title">ResourceHub</h1>
<!-- ChatBot -->
<button class="chatbot__button">
<span class="material-symbols-outlined">ChatBot</span>
<span class="material-symbols-outlined">close</span>
</button>
<div class="chatbot">
<div class="chatbot__header">
<h3 class="chatbox__title">ResourceHub</h3>
<span class="material-symbols-outlined">close</span>
</div>
<ul class="chatbot__box">
<li class="chatbot__chat incoming">
<p>Welcome ! to ChatBot...</p>
</li>
<li class="chatbot__chat outgoing">
<!-- <p>...</p> -->
</li>
</ul>
<div class="chatbot__input-box">
<textarea class="chatbot__textarea" placeholder="Enter a message..." required></textarea>
<span id="send-btn" class="material-symbols-outlined">send</span>
</div>
</div>
<!-- ChatBot html close -->
<div class="search-container">
<input type="text" class="search-input" placeholder="Search..." onkeyup="filterCards()">
</div>
<div id="rate-limit-message" style="display: none; color: red;"></div>
<div id="card-container"></div>
<script src="app.js"></script>
<script src="chatbot.js"></script>
</body>

</html>
<link rel="stylesheet" href="mainstyle.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.6/lottie.min.js"></script>
<style>
Expand Down