ソースを参照

Updated the code for frontend of the chatbot

rota3015 8 ヶ月 前
コミット
09725f9709
1 ファイル変更381 行追加1 行削除
  1. 381 1
      _includes/header.html

+ 381 - 1
_includes/header.html

@@ -1,4 +1,9 @@
 <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
+<link rel="stylesheet"
+  href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" />
+<link rel="stylesheet"
+  href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@48,400,1,0" />
+
 
 <!-- <link rel="stylesheet" href="{{ " /css/main.css" | prepend: site.baseurl }}"> -->
 <style>
@@ -120,6 +125,231 @@
     cursor: pointer;
     background-color: #d3a500
   }
+
+  @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap');
+
+* {
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
+    font-family: "Poppins", sans-serif;
+}
+
+.CRChatbot {
+    background: #E3F2FD;
+}
+
+.chatbot-toggler {
+    position: fixed;
+    bottom: 30px;
+    right: 35px;
+    outline: none;
+    border: none;
+    height: 50px;
+    width: 50px;
+    display: flex;
+    cursor: pointer;
+    align-items: center;
+    justify-content: center;
+    border-radius: 50%;
+    background: #FFC907;
+    transition: all 0.2s ease;
+}
+
+.CRChatbot.show-chatbot .chatbot-toggler {
+    transform: rotate(90deg);
+}
+
+.chatbot-toggler span {
+    color: #fff;
+    position: absolute;
+}
+
+.chatbot-toggler span:last-child,
+.CRChatbot.show-chatbot .chatbot-toggler span:first-child {
+    opacity: 0;
+}
+
+.CRChatbot.show-chatbot .chatbot-toggler span:last-child {
+    opacity: 1;
+}
+
+.chatbot {
+    position: fixed;
+    right: 35px;
+    bottom: 90px;
+    width: 420px;
+    background: #fff;
+    border-radius: 15px;
+    overflow: hidden;
+    opacity: 0;
+    pointer-events: none;
+    transform: scale(0.5);
+    transform-origin: bottom right;
+    box-shadow: 0 0 128px 0 rgba(0, 0, 0, 0.1),
+        0 32px 64px -48px rgba(0, 0, 0, 0.5);
+    transition: all 0.1s ease;
+}
+
+.CRChatbot.show-chatbot .chatbot {
+    opacity: 1;
+    pointer-events: auto;
+    transform: scale(1);
+}
+
+.chatbot header {
+    padding: 16px 0;
+    position: relative;
+    text-align: center;
+    color: #fff;
+    background: #FFC907;
+    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+
+.chatbot header span {
+    position: absolute;
+    right: 15px;
+    top: 50%;
+    display: none;
+    cursor: pointer;
+    transform: translateY(-50%);
+}
+
+header h2 {
+    font-size: 1.4rem;
+}
+
+.chatbot .chatbox {
+    overflow-y: auto;
+    height: 510px;
+    padding: 30px 20px 100px;
+}
+
+.chatbot :where(.chatbox, textarea)::-webkit-scrollbar {
+    width: 6px;
+}
+
+.chatbot :where(.chatbox, textarea)::-webkit-scrollbar-track {
+    background: #fff;
+    border-radius: 25px;
+}
+
+.chatbot :where(.chatbox, textarea)::-webkit-scrollbar-thumb {
+    background: #ccc;
+    border-radius: 25px;
+}
+
+.chatbox .chat {
+    display: flex;
+    list-style: none;
+}
+
+.chatbox .outgoing {
+    margin: 20px 0;
+    justify-content: flex-end;
+}
+
+.chatbox .incoming span {
+    width: 32px;
+    height: 32px;
+    color: #fff;
+    cursor: default;
+    text-align: center;
+    line-height: 32px;
+    align-self: flex-end;
+    background:#FFC907;
+    border-radius: 4px;
+    margin: 0 10px 7px 0;
+}
+
+.chatbox .chat p {
+    white-space: pre-wrap;
+    padding: 12px 16px;
+    border-radius: 10px 10px 0 10px;
+    max-width: 75%;
+    color: #fff;
+    font-size: 0.95rem;
+    background: #FFC907;
+}
+
+.chatbox .incoming p {
+    border-radius: 10px 10px 10px 0;
+}
+
+.chatbox .chat p.error {
+    color: #721c24;
+    background: #f8d7da;
+}
+
+.chatbox .incoming p {
+    color: #000;
+    background: #f2f2f2;
+}
+
+.chatbot .chat-input {
+    display: flex;
+    gap: 5px;
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    background: #fff;
+    padding: 3px 20px;
+    border-top: 1px solid #ddd;
+}
+
+.chat-input textarea {
+    height: 55px;
+    width: 100%;
+    border: none;
+    outline: none;
+    resize: none;
+    max-height: 180px;
+    padding: 15px 15px 15px 0;
+    font-size: 0.95rem;
+}
+
+.chat-input span {
+    align-self: flex-end;
+    color:#FFC907;
+    cursor: pointer;
+    height: 55px;
+    display: flex;
+    align-items: center;
+    visibility: hidden;
+    font-size: 1.35rem;
+}
+
+.chat-input textarea:valid~span {
+    visibility: visible;
+}
+
+@media (max-width: 490px) {
+    .chatbot-toggler {
+        right: 20px;
+        bottom: 20px;
+    }
+
+    .chatbot {
+        right: 0;
+        bottom: 0;
+        height: 100%;
+        border-radius: 0;
+        width: 100%;
+    }
+
+    .chatbot .chatbox {
+        height: 90%;
+        padding: 25px 15px 100px;
+    }
+
+    .chatbot .chat-input {
+        padding: 5px 15px;
+    }
+
+    .chatbot header span {
+        display: block;
+    }
+}
 </style>
 
 <header class="site-header">
@@ -175,7 +405,8 @@
       </div>
   </div>
 
-    <div id="navBar" class="modal" style="width: 40%; height: 15%; padding-top: 1%; flex-direction: column; justify-content: center; align-items: center;">
+  <div id="navBar" class="modal"
+    style="width: 40%; height: 15%; padding-top: 1%; flex-direction: column; justify-content: center; align-items: center;">
     <div id="emailCode" style="align-items: center; text-align: center;">
       <label for="emailInput">Enter your email:</label>
       <input type="email" id="emailInput" v-model="loginEmail" required>
@@ -198,10 +429,158 @@
     </div>
   </div>
   </nav>
+
+  <!-- <!DOCTYPE html>
+  <html lang="en" dir="ltr">
+
+  <head>
+    <meta charset="utf-8">
+    <title>Chatbot in JavaScript | CodingNepal</title>
+    <link rel="stylesheet" href="style.css">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <script src="script.js" defer></script>
+  </head> -->
+
+  <div class="CRChatbot">
+    <button class="chatbot-toggler">
+      <span class="material-symbols-rounded">mode_comment</span>
+      <span class="material-symbols-outlined">close</span>
+    </button>
+    <div class="chatbot">
+      <header>
+        <h2>Chatbot</h2>
+        <span class="close-btn material-symbols-outlined">close</span>
+      </header>
+      <ul class="chatbox">
+        <li class="chat incoming">
+          <span class="material-symbols-outlined">smart_toy</span>
+          <p>Hi there 👋<br>How can I help you today?</p>
+        </li>
+      </ul>
+      <div class="chat-input">
+        <textarea placeholder="Enter a message..." spellcheck="false" required></textarea>
+        <span id="send-btn" class="material-symbols-rounded">send</span>
+      </div>
+    </div>
   </div>
+
 </header>
 
 <script>
+  const chatbotToggler = document.querySelector(".chatbot-toggler");
+  const closeBtn = document.querySelector(".close-btn");
+  const chatbox = document.querySelector(".chatbox");
+  const chatInput = document.querySelector(".chat-input textarea");
+  const sendChatBtn = document.querySelector(".chat-input span");
+
+  let userMessage = null; // Variable to store user's message
+  const API_KEY = "PASTE-YOUR-API-KEY"; // Paste your API key here
+  const inputInitHeight = chatInput.scrollHeight;
+
+  const createChatLi = (message, className) => {
+    // Create a chat <li> element with passed message and className
+    const chatLi = document.createElement("li");
+    chatLi.classList.add("chat", `${className}`);
+    let chatContent = className === "outgoing" ? `<p></p>` : `<span class="material-symbols-outlined">smart_toy</span><p></p>`;
+    chatLi.innerHTML = chatContent;
+    chatLi.querySelector("p").textContent = message;
+    return chatLi; // return chat <li> element
+  }
+
+  // const generateResponse = (chatElement) => {
+  //   const API_URL = "https://api.openai.com/v1/chat/completions";
+  //   const messageElement = chatElement.querySelector("p");
+
+  //   // Define the properties and message for the API request
+  //   const requestOptions = {
+  //     method: "POST",
+  //     headers: {
+  //       "Content-Type": "application/json",
+  //       "Authorization": `Bearer ${API_KEY}`
+  //     },
+  //     body: JSON.stringify({
+  //       model: "gpt-3.5-turbo",
+  //       messages: [{ role: "user", content: userMessage }],
+  //     })
+  //   }
+
+  //   // Send POST request to API, get response and set the reponse as paragraph text
+  //   fetch(API_URL, requestOptions).then(res => res.json()).then(data => {
+  //     messageElement.textContent = data.choices[0].message.content.trim();
+  //   }).catch(() => {
+  //     messageElement.classList.add("error");
+  //     messageElement.textContent = "Oops! Something went wrong. Please try again.";
+  //   }).finally(() => chatbox.scrollTo(0, chatbox.scrollHeight));
+  // }
+
+    const generateResponse = (chatElement) => {
+      const apiUrl = new URL("http://127.0.0.1:5000/request");
+      const params = { question: userMessage };
+      apiUrl.search = new URLSearchParams(params).toString();
+      const messageElement = chatElement.querySelector("p");
+
+        // Define the properties and message for the API request
+      const requestOptions = {
+        method: "GET",
+        headers: {
+          "Content-Type": "application/json",
+        },
+      };
+
+        // Send POST request to API, get response and set the reponse as paragraph text
+        fetch(apiUrl, requestOptions)
+        .then(res => res.json())
+        .then(data => {
+          console.log(data)
+          const community = data.community.replace(/\n/g, '').trim()
+          const responseMessage = `Following is the most suitable community rule we found based on description:\n${community} \n link: <a href="${data.link}" target="_blank">${data.link}</a>`;
+          messageElement.innerHTML = responseMessage;
+
+        }).catch((err) => {
+          messageElement.classList.add("error");
+          messageElement.textContent = "Oops! Something went wrong. Please try again.";
+        }).finally(() => chatbox.scrollTo(0, chatbox.scrollHeight));
+      }
+  const handleChat = () => {
+    userMessage = chatInput.value.trim(); // Get user entered message and remove extra whitespace
+    if (!userMessage) return;
+
+    // Clear the input textarea and set its height to default
+    chatInput.value = "";
+    chatInput.style.height = `${inputInitHeight}px`;
+
+    // Append the user's message to the chatbox
+    chatbox.appendChild(createChatLi(userMessage, "outgoing"));
+    chatbox.scrollTo(0, chatbox.scrollHeight);
+
+    setTimeout(() => {
+      // Display "Thinking..." message while waiting for the response
+      const incomingChatLi = createChatLi("Thinking...", "incoming");
+      chatbox.appendChild(incomingChatLi);
+      chatbox.scrollTo(0, chatbox.scrollHeight);
+      generateResponse(incomingChatLi);
+    }, 600);
+  }
+
+  chatInput.addEventListener("input", () => {
+    // Adjust the height of the input textarea based on its content
+    chatInput.style.height = `${inputInitHeight}px`;
+    chatInput.style.height = `${chatInput.scrollHeight}px`;
+  });
+
+  chatInput.addEventListener("keydown", (e) => {
+    // If Enter key is pressed without Shift key and the window 
+    // width is greater than 800px, handle the chat
+    if (e.key === "Enter" && !e.shiftKey && window.innerWidth > 800) {
+      e.preventDefault();
+      handleChat();
+    }
+  });
+
+  sendChatBtn.addEventListener("click", handleChat);
+  closeBtn.addEventListener("click", () => document.querySelector(".CRChatbot").classList.remove("show-chatbot"));
+  chatbotToggler.addEventListener("click", () => document.querySelector(".CRChatbot").classList.toggle("show-chatbot"));
+
   function toggleDropdown() {
     var dropdown = document.getElementById('logout');
     dropdown.classList.toggle('active');
@@ -342,4 +721,5 @@
     },
   });
 
+  
 </script>