Skip to content

Commit

Permalink
added ai chatbot to the site
Browse files Browse the repository at this point in the history
Signed-off-by: Swapnoneel Saha <swapnoneelsaha111@gmail.com>
  • Loading branch information
Swpn0neel committed Oct 10, 2024
1 parent eb9de8a commit 710f20a
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"lint": "^0.8.19",
"lucide-react": "^0.451.0",
"prism-react-renderer": "^2.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
213 changes: 213 additions & 0 deletions src/components/ChatBot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import React, {useState, useCallback, useRef, useEffect} from "react";
import {MessageCircle, X} from "lucide-react";

function textFormat(text) {
let block = 0;
let code = ``;
let lang = "";
let heading = 2;
let output = ``;

for (let i = 0; i < text.length; i++) {
if (text.substring(i, i + 3) === "```") {
i += 2;
if (block === 0) {
block = 1;
lang = "";
while (i < text.length && text.charAt(i) !== "\n") {
lang += text.charAt(i++);
}
} else {
output += code;
code = ``;
lang = "";
block = 0;
}
} else if (block === 0) {
if (text.substring(i, i + 3) === "###") {
i += 2;
heading = 3;
output += `\n\n`;
} else if (text.substring(i, i + 2) === "##") {
i += 1;
heading = 2;
output += `\n\n`;
} else if (text.substring(i, i + 1) == "#") {
heading = 1;
output += `\n\n`;
} else if (text.substring(i, i + 1) == "<") {
i++;
while (
i < text.length &&
text.substring(i, i + 2) != "/>" &&
text.substring(i, i + 1) != ">"
) {
i++;
}
} else if (text.substring(i, i + 2) === "**") {
i += 1;
} else if (text.substring(i, i + 2) === "* ") {
i += 1;
output += `\n• `;
} else if (text.charAt(i) === "\n") {
output += `\n`;
} else {
output += text.charAt(i);
}
} else {
code += text.charAt(i);
}
}

return output;
}

export default function ChatBot() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const messagesEndRef = useRef(null);

const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({behavior: "smooth"});
};

useEffect(() => {
scrollToBottom();
}, [messages]);

const sendMessage = useCallback(async () => {
if (!input.trim() || isLoading) return;

const userMessage = {text: input, sender: "user"};
setMessages((prevMessages) => [...prevMessages, userMessage]);
setIsLoading(true);

try {
const apiRes = await fetch(
"https://keploy-api.abhishekkushwaha.me/chat",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({question: input}),
}
);

if (!apiRes.ok) {
throw new Error(`HTTP error! status: ${apiRes.status}`);
}

const {answer} = await apiRes.json();

setMessages((prevMessages) => [
...prevMessages,
{text: answer, sender: "bot"},
]);
} catch (error) {
console.error("Error fetching response from Keploy API", error);
setMessages((prevMessages) => [
...prevMessages,
{
text: "Sorry, there was an error processing your request.",
sender: "bot",
},
]);
} finally {
setIsLoading(false);
setInput("");
}
}, [input, isLoading]);

const handleKeyPress = useCallback(
(e) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
},
[sendMessage]
);

const toggleChat = useCallback(() => {
setIsOpen((prev) => !prev);
}, []);

return (
<div className="fixed bottom-16 right-16 z-50">
{!isOpen && (
<button
onClick={toggleChat}
className="rounded-full bg-[#FF914D] p-4 text-white shadow-lg transition-all duration-300 ease-in-out hover:scale-110 hover:bg-[#FF914D] hover:shadow-2xl"
>
<MessageCircle size={24} />
</button>
)}
{isOpen && (
<div className="flex h-[500px] w-80 flex-col rounded-lg bg-white shadow-xl sm:w-96">
<div className="flex items-center justify-between border-b p-4">
<h3 className="text-lg font-semibold text-black">Chat with us</h3>
<button
onClick={toggleChat}
className="text-gray-500 hover:text-gray-700"
>
<X size={24} />
</button>
</div>
<div className="flex h-full flex-grow flex-col bg-gray-100">
<div className="flex-1 overflow-y-auto p-4">
{messages.map((msg, index) => (
<div
key={index}
className={`mb-2 ${
msg.sender === "user" ? "text-right" : "text-left"
}`}
>
<span
className={`inline-block rounded-lg px-4 py-2 ${
msg.sender === "user"
? "bg-[#FF914D] text-white"
: "bg-gray-300 text-black"
}`}
>
{textFormat(msg.text)}
</span>
</div>
))}
{isLoading && (
<div className="text-center text-gray-500">
Bot is typing...
</div>
)}
<div ref={messagesEndRef} />
</div>

<div className="border-t bg-white p-4">
<div className="flex items-center space-x-4">
<input
type="text"
className="flex-1 rounded-lg border bg-white px-4 py-2 text-black focus:border-[#FF914D] focus:outline-none"
placeholder="Type your message"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={handleKeyPress}
disabled={isLoading}
/>
<button
className="rounded-lg bg-[#FF914D] px-4 py-2 text-white disabled:opacity-80"
onClick={sendMessage}
disabled={isLoading || !input.trim()}
>
{isLoading ? "Sending..." : "Send"}
</button>
</div>
</div>
</div>
</div>
)}
</div>
);
}
3 changes: 3 additions & 0 deletions src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import {Community, KeployCloud, Resources, QuickStart} from "../components";
import {GSoC} from "../components/GSoC";
import {Intro} from "../components";
import ChatBot from "../components/ChatBot";

export default function Home() {
const context = useDocusaurusContext();
const {siteConfig = {}} = context;
Expand All @@ -15,6 +17,7 @@ export default function Home() {
description={`${siteConfig.tagline}`}
>
<main className="mx-auto max-w-screen-lg p-6 md:p-10">
<ChatBot />
<QuickStart />
{/* <Hacktoberfest /> */}
{/*<GitTogether />*/}
Expand Down
15 changes: 8 additions & 7 deletions static/scripts/chat.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// hubspot.js
const script = document.createElement("script");
script.type = "text/javascript";
script.id = "hs-script-loader";
script.async = true;
script.defer = true;
script.src = "//js-na1.hs-scripts.com/43912677.js";
document.head.appendChild(script);

// const script = document.createElement("script");
// script.type = "text/javascript";
// script.id = "hs-script-loader";
// script.async = true;
// script.defer = true;
// script.src = "//js-na1.hs-scripts.com/43912677.js";
// document.head.appendChild(script);

0 comments on commit 710f20a

Please sign in to comment.