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 createChatLi = ( message , className ) => {
12
+ // Create a chat <li> element with passed message and className
13
+ const chatLi = document . createElement ( "li" ) ;
14
+ chatLi . classList . add ( "chat" , `${ className } ` ) ;
15
+ let chatContent = className === "outgoing" ? `<p></p>` : `<span class="material-symbols-outlined">smart_toy</span><p></p>` ;
16
+ chatLi . innerHTML = chatContent ;
17
+ chatLi . querySelector ( "p" ) . textContent = message ;
18
+ return chatLi ; // return chat <li> element
19
+ }
20
+
21
+ const generateResponse = ( chatElement ) => {
22
+ const API_URL = "https://api.openai.com/v1/chat/completions" ;
23
+ const messageElement = chatElement . querySelector ( "p" ) ;
24
+
25
+ // Define the properties and message for the API request
26
+ const requestOptions = {
27
+ method : "POST" ,
28
+ headers : {
29
+ "Content-Type" : "application/json" ,
30
+ "Authorization" : `Bearer ${ API_KEY } `
31
+ } ,
32
+ body : JSON . stringify ( {
33
+ model : "gpt-3.5-turbo" ,
34
+ messages : [ { role : "user" , content : userMessage } ] ,
35
+ } )
36
+ }
37
+
38
+ // Send POST request to API, get response and set the reponse as paragraph text
39
+ fetch ( API_URL , requestOptions ) . then ( res => res . json ( ) ) . then ( data => {
40
+ messageElement . textContent = data . choices [ 0 ] . message . content . trim ( ) ;
41
+ } ) . catch ( ( ) => {
42
+ messageElement . classList . add ( "error" ) ;
43
+ messageElement . textContent = "Oops! Something went wrong. Please try again." ;
44
+ } ) . finally ( ( ) => chatbox . scrollTo ( 0 , chatbox . scrollHeight ) ) ;
45
+ }
46
+
47
+ const handleChat = ( ) => {
48
+ userMessage = chatInput . value . trim ( ) ; // Get user entered message and remove extra whitespace
49
+ if ( ! userMessage ) return ;
50
+
51
+ // Clear the input textarea and set its height to default
52
+ chatInput . value = "" ;
53
+ chatInput . style . height = `${ inputInitHeight } px` ;
54
+
55
+ // Append the user's message to the chatbox
56
+ chatbox . appendChild ( createChatLi ( userMessage , "outgoing" ) ) ;
57
+ chatbox . scrollTo ( 0 , chatbox . scrollHeight ) ;
58
+
59
+ setTimeout ( ( ) => {
60
+ // Display "Thinking..." message while waiting for the response
61
+ const incomingChatLi = createChatLi ( "Thinking..." , "incoming" ) ;
62
+ chatbox . appendChild ( incomingChatLi ) ;
63
+ chatbox . scrollTo ( 0 , chatbox . scrollHeight ) ;
64
+ generateResponse ( incomingChatLi ) ;
65
+ } , 600 ) ;
66
+ }
67
+
68
+ chatInput . addEventListener ( "input" , ( ) => {
69
+ // Adjust the height of the input textarea based on its content
70
+ chatInput . style . height = `${ inputInitHeight } px` ;
71
+ chatInput . style . height = `${ chatInput . scrollHeight } px` ;
72
+ } ) ;
73
+
74
+ chatInput . addEventListener ( "keydown" , ( e ) => {
75
+ // If Enter key is pressed without Shift key and the window
76
+ // width is greater than 800px, handle the chat
77
+ if ( e . key === "Enter" && ! e . shiftKey && window . innerWidth > 800 ) {
78
+ e . preventDefault ( ) ;
79
+ handleChat ( ) ;
80
+ }
81
+ } ) ;
82
+
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" ) ) ;
0 commit comments