-
Notifications
You must be signed in to change notification settings - Fork 409
Johannas Chatbot #277
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
base: main
Are you sure you want to change the base?
Johannas Chatbot #277
Changes from all commits
bdfba28
ad44a55
0e27aae
b2879b3
48206fe
dfac772
3de00ea
0aac697
833c991
97bbd41
05e7a15
4cd08c8
6e0cfac
e01aa98
690df89
0c16fee
bf9c1ce
5c50c03
c77dd79
88ff583
cfb68b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,28 @@ | ||
| # Project Name | ||
| # Project Chatbot | ||
|
|
||
| Replace this readme with your own information about your project. | ||
| The assignment was to build a functional chatbot interface using JavaScript, HTML, and CSS. The chatbot should interact with users, ask questions, display messages, and respond with precision. | ||
|
|
||
| Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. | ||
| ## The problems | ||
|
|
||
| ## The problem | ||
| **1. Creativity went wild** | ||
| When I started working on my project, my creativity took over when I read, "Step 2 - Have it your way 👋". I envisioned a coffee shop chatbot, like a Starbucks order flow, but soon realized that my idea was far too complex. Options for hot or cold drinks, different coffee shop locations, milk choices depending on the coffee type, drop-downs, buttons - the scope was way beyond my skills. Instead of realizing this right away, I stumbled across more issues as I progressed, forcing me to simplify my plan. I read through all the instructions before picking up my code again, and limited the scope to be more like my previous project (Project Javascript Pizzeria) with a very limited amount of options for the user, similar if else statement, etc. | ||
|
|
||
| Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? | ||
| **2. Attention to details issues** | ||
| I was a bit hasty and made several spelling mistakes, forgot to delete parts of the code and variables when I renamed/replaced/stopped using things in the code, which led to unnecessary (and time consuming) issues that could have been avoided. | ||
|
|
||
| ## If you had more time, what would be next? | ||
|
|
||
| *** UPDATE *** I rearranged the script, to go from the bottom up, and this solved most of the problems below. | ||
|
|
||
| **1.** Figure out a way to move line 17-27 further down in the script. It looks awkward to me to have "Handle user name input" above the "Start conversation", but the code broke when I moved it so I didn't dare to continue since time was running out. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good approach! Have a look at the notes from last week's Thursday session to learn more |
||
|
|
||
| **2.** This part was suggested by ChatGPT: `document.addEventListener("DOMContentLoaded", () => {`. While I understand that it ensures all elements are fully loaded before the code runs, I haven't grasped why it's necessary in my code or when to use it. If I had more time, I would try to figure that out. | ||
|
|
||
| **3.** I used `nameForm.removeEventListener("submit", handleUserInput)` because I wanted the "Start conversation" button to be the only visible option in the chat, forcing the user to click it to begin, but the event listener for the name form is still active. If I had more time, I would address this issue. | ||
|
|
||
| **4.** The buttons seem to have a life of their own, and the input field remains visible in the background (likely related to the previous issue). If I had more time, I would fix this, but at this point, I'm just glad they're working. I struggled with this earlier in the project and almost abandoned the idea altogether. | ||
|
Comment on lines
+21
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for sharing your progress Johanna! In this project it's important to guide the user on what they need to be doing, so I would like you to actually look into this. It shouldn't be possible for the user to write their name:
|
||
|
|
||
| ## View it live | ||
|
|
||
| Have you deployed your project somewhere? Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. | ||
| **Netlify:** https://johannaschatbot.netlify.app | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,162 @@ | ||
| //Global LET variables that will be used in the confirmation | ||
|
|
||
| let userName = '' | ||
| let selectedCoffee = '' | ||
| let sizeChoice = '' | ||
| let coffeeShop = '' | ||
|
|
||
| // DOM selectors (variables that point to selected DOM elements) goes here 👇 | ||
| const chat = document.getElementById('chat') | ||
| const startButton = document.getElementById('start-button') | ||
| const inputWrapper = document.getElementById('input-wrapper') | ||
| const userInput = document.getElementById("user-input") | ||
| const nameForm = document.getElementById('name-form') | ||
|
|
||
| // 10. Handle summary | ||
|
|
||
| const showSummary = () => { | ||
| showMessage(`Thank you, ${userName}, for your order of ${coffeeChoice} (${sizeChoice} size), which you will pick up at Coffee JoE in ${coffeeShop}.`, 'bot') | ||
|
|
||
| //Remove input field after Confirmation | ||
|
|
||
| document.getElementById('name-form').remove() | ||
| } | ||
| // 9. Handle Coffeeshop input | ||
| const userAnswer = (selectCoffeeShop) => { | ||
| coffeeShop = selectCoffeeShop | ||
| showMessage(` Coffee JoE in ${coffeeShop}.`, 'user') | ||
| showMessage(`You have selected ${coffeeShop}.`, 'bot') | ||
|
|
||
| //Remove Coffeeshop buttons | ||
| document.getElementById("stockholm").remove() | ||
| document.getElementById("gothenburg").remove() | ||
| document.getElementById("kiruna").remove() | ||
| document.getElementById("falun").remove() | ||
| setTimeout(showSummary, 3000) // Move on to Summary | ||
| } | ||
|
|
||
| // 8. Select Coffee Shop | ||
| const handleCoffeeShopInput = () => { | ||
| inputWrapper.classList.add("hidden") | ||
| showMessage("Where would you like to pick up your coffee?", 'bot') | ||
| chat.innerHTML += ` | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that you use append += with innerHTML frequently throughout your code. (I just used innerHTML = (without the +)) I also noticed that you frequently used .remove() .. I wonder if these are related. If you took out the append with innerHTML would you need to use remove() ? Because I think innerHTML = automatically replaces whatever was there previously, and therefore you could probably simplify a lot of the code. |
||
| <section class="bot-msg"> | ||
| <button id="stockholm" class="selection-button">Stockholm</button> | ||
| <button id="gothenburg" class="selection-button">Gothenburg</button> | ||
| <button id="kiruna" class="selection-button">Kiruna</button> | ||
| <button id="falun" class="selection-button">Falun</button> | ||
| </section> | ||
| ` | ||
| document.getElementById('stockholm').addEventListener("click", () => userAnswer('Stockholm')) | ||
| document.getElementById('gothenburg').addEventListener("click", () => userAnswer('Gothenburg')) | ||
| document.getElementById('kiruna').addEventListener("click", () => userAnswer('Kiruna')) | ||
| document.getElementById('falun').addEventListener("click", () => userAnswer('Falun')) | ||
| } | ||
|
|
||
| // 7. Handle coffee size input | ||
| const handleSizeChoice = (size) => { | ||
| sizeChoice = size | ||
| showMessage(`${size} size!`, 'user') | ||
|
|
||
| document.getElementById("regularButton").remove() | ||
| document.getElementById("smallButton").remove() | ||
|
|
||
| showMessage("Great choice! Your coffee is almost on the way.", 'bot') | ||
|
|
||
| setTimeout(handleCoffeeShopInput, 3000) // Move on to Coffee shop question | ||
| } | ||
|
|
||
| // 6. Coffee size | ||
| const askForSize = () => { | ||
| inputWrapper.classList.add("hidden") | ||
| showMessage("What size would you like?", 'bot') | ||
|
|
||
| // Add two Size buttons | ||
| chat.innerHTML += ` | ||
| <section class="bot-msg"> | ||
| <button id="regularButton" class="selection-button">Regular</button> | ||
| <button id="smallButton" class="selection-button">Small</button> | ||
| </section> | ||
| ` | ||
|
|
||
| document.getElementById("regularButton").addEventListener("click", () => handleSizeChoice("Regular")) | ||
| document.getElementById("smallButton").addEventListener("click", () => handleSizeChoice("Small")) | ||
| } | ||
| // 5. Handle Coffee choice input | ||
|
|
||
| const handleCoffeeInput = (selectedCoffee) => { | ||
| coffeeChoice = selectedCoffee // Update the global variable | ||
| if (coffeeChoice === "Pumpkin Spice Latte") { | ||
| showMessage(`${coffeeChoice}, please.`, 'user') | ||
| showMessage("Ah, Pumpkin Spice Latte, perfect choice!", 'bot') | ||
| } else if (coffeeChoice === "Espresso") { | ||
| showMessage(`${coffeeChoice}, please.`, 'user') | ||
| showMessage("An Espresso coming up! Excellent choice.", 'bot') | ||
| } else if (coffeeChoice === "Cappuccino") { | ||
| showMessage(`${coffeeChoice}, please.`, 'user') | ||
| showMessage("Creamy Cappuccino it is!", 'bot') | ||
| } else if (coffeeChoice === "Americano") { | ||
| showMessage(`${coffeeChoice}, please.`, 'user') | ||
| showMessage("A classic Americano for you!", 'bot') | ||
| } else { | ||
| showMessage(`${coffeeChoice}, please.`, 'user') | ||
| showMessage(`${coffeeChoice} sounds great, but we don't have that option right now!`, 'bot') | ||
| return | ||
| } | ||
|
|
||
| // Functions goes here 👇 | ||
| document.getElementById("pumpkin").remove() | ||
| document.getElementById("cappuccino").remove() | ||
| document.getElementById("americano").remove() | ||
| document.getElementById("espresso").remove() | ||
|
|
||
| // A function that will add a chat bubble in the correct place based on who the sender is | ||
| setTimeout(askForSize, 2000) // Move on to Ask for size | ||
| } | ||
|
|
||
| // 4. Select Coffee | ||
|
|
||
| const selectCoffee = () => { | ||
| inputWrapper.classList.add("hidden") | ||
|
|
||
| showMessage(`Nice to meet you, ${userName}.`, 'bot') | ||
|
|
||
| setTimeout(() => { | ||
| showMessage(`Please start your order by selecting your coffee. Here are your options:`, 'bot') | ||
|
|
||
| chat.innerHTML += ` | ||
| <section class="bot-msg"> | ||
| <button id="pumpkin" class="selection-button">Pumpkin Spice Latte</button> | ||
| <button id="cappuccino" class="selection-button">Cappuccino</button> | ||
| <button id="americano" class="selection-button">Americano</button> | ||
| <button id="espresso" class="selection-button">Espresso</button> | ||
| </section> | ||
| ` | ||
|
|
||
| document.getElementById("pumpkin").addEventListener("click", () => handleCoffeeInput("Pumpkin Spice Latte")) | ||
| document.getElementById("cappuccino").addEventListener("click", () => handleCoffeeInput("Cappuccino")) | ||
| document.getElementById("americano").addEventListener("click", () => handleCoffeeInput("Americano")) | ||
| document.getElementById("espresso").addEventListener("click", () => handleCoffeeInput("Espresso")) | ||
|
|
||
| nameForm.removeEventListener("submit", handleUserInput) // Remove Event listener for Name | ||
|
|
||
| }, 1500) //Move on to Handle Coffee choice input | ||
| } | ||
|
|
||
| // 3. Handle user name input | ||
| const handleUserInput = (event) => { | ||
| event.preventDefault() | ||
|
|
||
| userName = userInput.value | ||
| showMessage(userName, "user") | ||
| userInput.value = "" // Clear input field | ||
|
|
||
| document.getElementById('input-wrapper').remove() | ||
|
|
||
| setTimeout(selectCoffee, 1000) // Move on to Select coffee | ||
| } | ||
|
|
||
| // Funtion to show messages from bot and user | ||
| const showMessage = (message, sender) => { | ||
| // The if statement checks if the sender is the user and if that's the case it inserts | ||
| // an HTML section inside the chat with the posted message from the user | ||
| // Posted message from the user | ||
| if (sender === 'user') { | ||
| chat.innerHTML += ` | ||
| <section class="user-msg"> | ||
|
|
@@ -16,8 +166,7 @@ const showMessage = (message, sender) => { | |
| <img src="assets/user.png" alt="User" /> | ||
| </section> | ||
| ` | ||
| // The else if statement checks if the sender is the bot and if that's the case it inserts | ||
| // an HTML section inside the chat with the posted message from the bot | ||
| // Posted message from the bot | ||
| } else if (sender === 'bot') { | ||
| chat.innerHTML += ` | ||
| <section class="bot-msg"> | ||
|
|
@@ -29,25 +178,26 @@ const showMessage = (message, sender) => { | |
| ` | ||
| } | ||
|
|
||
| // This little thing makes the chat scroll to the last message when there are too many to | ||
| // be shown in the chat box | ||
| chat.scrollTop = chat.scrollHeight | ||
| // Scroll to the last message when chat is too long. | ||
| // requestAnimationFrame to avoid scrolling to see selection-buttons in the chat | ||
| requestAnimationFrame(() => { | ||
| chat.scrollTop = chat.scrollHeight | ||
| }) | ||
| } | ||
| startButton.addEventListener("click", () => { | ||
| startChat() | ||
| document.getElementById('name-form').addEventListener("submit", handleUserInput) | ||
| }) | ||
|
|
||
| // 2. Greet user | ||
|
|
||
| // A function to start the conversation | ||
| const greetUser = () => { | ||
| // Here we call the function showMessage, that we declared earlier with the argument: | ||
| // "Hello there, what's your name?" for message, and the argument "bot" for sender | ||
| showMessage("Hello there, what's your name?", 'bot') | ||
| // Just to check it out, change 'bot' to 'user' here 👆 and see what happens | ||
| showMessage("Hello fellow Java Junkie! What's your name?", 'bot') | ||
| } | ||
|
|
||
| // Eventlisteners goes here 👇 | ||
|
|
||
| // Here we invoke the first function to get the chatbot to ask the first question when | ||
| // the website is loaded. Normally we invoke functions like this: greeting() | ||
| // To add a little delay to it, we can wrap it in a setTimeout (a built in JavaScript function): | ||
| // and pass along two arguments: | ||
| // 1.) the function we want to delay, and 2.) the delay in milliseconds | ||
| // This means the greeting function will be called one second after the website is loaded. | ||
| setTimeout(greetUser, 1000) | ||
| //1. Click Start Conversation button | ||
| const startChat = () => { | ||
| greetUser() | ||
| startButton.classList.add("hidden") // Hide Start conversation button when clicked | ||
| document.getElementById('name-form').classList.add('show') // Show name input field | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for sharing your approach, I found this very relatable - especially the creativity going wild and attention to detail issues 😅