diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..b28757dc Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 60f55e53..da37a728 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,17 @@ -# Project Name +# Project chatbot -Replace this readme with your own information about your project. - -Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. +My task was to develop an interactive chatbot in JavaScript where the user can communicate with the bot by entering their name and responding to various questions. I was to build upon the existing code by handling user inputs, controlling the flow of the conversation, and adding new features and effects such as conditional statements, different input types, and potentially sound. ## The problem -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? +To approach the problem, I started by carefully reading through the existing code (and watched Jennie's video) to understand how the chatbot was structured and which functions were already in place. I identified the key areas where I needed to add new functionality, such as handling user input, managing the conversation flow, and dynamically updating the content on the page. + +I used JavaScript, HTML, and CSS as the main technologies for this project. I utilized JavaScript to handle user interactions, create functions for different conversation stages, and control the timing of messages using setTimeout. In addition, I employed CSS to style the chat interface and make it visually appealing, and HTML to structure the content on the page. + +For planning, I outlined the conversation flow and identified key questions and answers to include. I then broke down the development into smaller tasks, such as creating event listeners for user inputs, implementing functions to handle specific stages of the conversation, and testing each step to ensure it worked correctly. + +If I had more time, I would further enhance the chatbot by adding more diverse response types, such as drop-down menus or clickable options, implementing additional sound effects, and optimizing the code to make it more scalable and efficient. ## 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. +https://cookiebot-lifeisbetterwithcookies.netlify.app/ diff --git a/code/.DS_Store b/code/.DS_Store new file mode 100644 index 00000000..40f57e5e Binary files /dev/null and b/code/.DS_Store differ diff --git a/code/assets/.DS_Store b/code/assets/.DS_Store new file mode 100644 index 00000000..b3c155c9 Binary files /dev/null and b/code/assets/.DS_Store differ diff --git a/code/assets/Userpic.png b/code/assets/Userpic.png new file mode 100644 index 00000000..b6a28cde Binary files /dev/null and b/code/assets/Userpic.png differ diff --git a/code/assets/botpic1.png b/code/assets/botpic1.png new file mode 100644 index 00000000..cc5b45c5 Binary files /dev/null and b/code/assets/botpic1.png differ diff --git a/code/assets/botpic2.png b/code/assets/botpic2.png new file mode 100644 index 00000000..3798b9dd Binary files /dev/null and b/code/assets/botpic2.png differ diff --git a/code/assets/chatsound.wav b/code/assets/chatsound.wav new file mode 100644 index 00000000..f9c70d9c Binary files /dev/null and b/code/assets/chatsound.wav differ diff --git a/code/assets/cookiemonster2.png b/code/assets/cookiemonster2.png new file mode 100644 index 00000000..a46ae2e4 Binary files /dev/null and b/code/assets/cookiemonster2.png differ diff --git a/code/assets/cookiemonster3.png b/code/assets/cookiemonster3.png new file mode 100644 index 00000000..0d7712a6 Binary files /dev/null and b/code/assets/cookiemonster3.png differ diff --git a/code/assets/userlogomonster.png b/code/assets/userlogomonster.png new file mode 100644 index 00000000..9e0ba924 Binary files /dev/null and b/code/assets/userlogomonster.png differ diff --git a/code/index.html b/code/index.html index 316eb187..a95969f8 100644 --- a/code/index.html +++ b/code/index.html @@ -1,23 +1,40 @@ - - - - - - Chatbot - - - -

Welcome to my chatbot!

+ + + + + + + + + + Cookiebot + + + + + + +
+ + + + +
-
+
+ + + + + + - - + - + \ No newline at end of file diff --git a/code/script.js b/code/script.js index 125d6904..5c1af7cf 100644 --- a/code/script.js +++ b/code/script.js @@ -1,53 +1,181 @@ -// DOM selectors (variables that point to selected DOM elements) goes here 👇 -const chat = document.getElementById('chat') +// DOM selectors -// Functions goes here 👇 +const chat = document.getElementById('chat'); +const nameInput = document.getElementById('name-input'); +const form = document.getElementById('name-form'); +const chatSound = document.getElementById('chatSound'); -// A function that will add a chat bubble in the correct place based on who the sender is +// Functions + +// Welcome the user back again +const goodbyeMessage = (choice) => { + if (choice === 'Yes') { // If yes, message that order is prepaired + showMessage(`Your order will be prepaired. Thank you for using the Cookiebot! 🍪`, 'bot'); + } else { // If no, massage that the order is canceled + showMessage(`No order has been placed. Hope we meet again soon!`, 'bot') + } +}; + +// User bubble show confirmation choice +const handleConfirmationChoice = (choice) => { + showMessage(`${choice}`, 'user'); + document.getElementById('buttonContainer').style.display = 'none'; // Hide buttons + setTimeout(() => goodbyeMessage(choice), 1000); +}; + +// Confirmation buttons +const createConfirmationButtons = () => { + form.style.display = 'none'; // Hide form + form.innerHTML = ` +
+ + +
+ `; + form.style.display = 'block'; // Show buttons + + // DOM, Event listeners and invoking yes or no buttons + document.getElementById('yesButton').addEventListener('click', () => handleConfirmationChoice('Yes')); + document.getElementById('noButton').addEventListener('click', () => handleConfirmationChoice('No')); +}; + +// Ask for order confirmation +// Also printing out correct price depending on drink or not +const askForOrderConfirmation = (choice) => { + let totalPrice = ''; + if (choice === 'Milk' || choice === 'Coffee') { + totalPrice = '$10'; + } else { + totalPrice = '$5'; + } + showMessage(`Wonderful! The total price will be ${totalPrice}, are you sure you'd like to place the order?`, 'bot') + createConfirmationButtons(); +}; + +// User bubble show drink choice and passes the choice to next function +const handleDrinkChoice = (choice) => { + showMessage(`${choice} please`, 'user'); + document.getElementById('buttonContainer').style.display = 'none'; // Hide buttons + setTimeout(() => askForOrderConfirmation(choice), 1000); +}; + +// Drink buttons +const createDrinkButtons = () => { + form.style.display = 'none'; // Hide form + form.innerHTML = ` +
+ + + +
+ `; + form.style.display = 'block'; // Show buttons + + // DOM, Event listeners and Invoking each drink button + document.getElementById('milk').addEventListener('click', () => handleDrinkChoice('Milk')); + document.getElementById('coffee').addEventListener('click', () => handleDrinkChoice('Coffee')); + document.getElementById('noDrink').addEventListener('click', () => handleDrinkChoice('No drink')); +}; + +// Asking for drink +const askForDrinkChoice = (choice) => { + showMessage(`Mmm ${choice}, great choice, would you like a drink?`, 'bot') + createDrinkButtons(); +}; + +// User bubble show cookie choice and passes the choice to next function +const handleCookieChoice = (choice) => { + showMessage(`I choose ${choice}!`, 'user'); + document.getElementById('buttonContainer').style.display = 'none'; // Hide buttons + setTimeout(() => askForDrinkChoice(choice), 1000); +}; + +// Cookie buttons +const createCookieButtons = () => { + form.style.display = 'none'; // hide form + form.innerHTML = ` +
+ + + +
+ `; + form.style.display = 'block'; // show buttons + + // Here I: + // 1.Select DOMs, + // 2.Add Event listeners + // 3.Invoking handleCookieChoice function + passes the cookie choice + document.getElementById('darkChocolate').addEventListener('click', () => handleCookieChoice('Dark chocolate')); + document.getElementById('milkChocolate').addEventListener('click', () => handleCookieChoice('Milk chocolate')); + document.getElementById('nutsChocolate').addEventListener('click', () => handleCookieChoice('Nuts and white chocolate')); +}; + +// Asking for what kind of cookie +const askForCookieChoice = (name) => { + showMessage(`Welcome ${name}! What kind of cookie would you like to order?`, 'bot'); + createCookieButtons(); +}; + +// Handeling the name input, if the user types nothing in the field +//the bot will ask again for name +// If the user print in a name, the program continues +const handleNameInput = (event) => { + event.preventDefault(); + const name = nameInput.value.trim(); // Trim is getting rid of spaces + if (name === '') { + showMessage(name, 'user'); + setTimeout(() => { // Using setTimeout to delay the bot message + showMessage(`Please type in your name...`, 'bot'); + form.addEventListener('submit', handleNameInput); // Invoking the function again + }, 1000); + } else { + showMessage(name, 'user'); + nameInput.value = ''; // Empty textfield + setTimeout(() => askForCookieChoice(name), 1000); // Continue with the next question + } +}; + +// Event listener for the form +form.addEventListener('submit', handleNameInput); + +// Funcion that shows diffrent chat bubbles depending on 'user' or 'bot' 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 if (sender === 'user') { chat.innerHTML += `

${message}

- User + User
- ` - // 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 + `; } else if (sender === 'bot') { chat.innerHTML += `
- Bot + Bot

${message}

- ` + `; } + // Chat sound every time showMessage is used + if (chatSound) { + chatSound.currentTime = 0; // to be able to also have chat sound on bot + chatSound.play().catch(error => { + console.error("Your browser do not support the video tag", error); + }); + } + setTimeout(() => { + chat.scrollTop = chat.scrollHeight; + }, 10); +}; - // 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 -} - -// A function to start the conversation +// Greeting message 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 -} - -// 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) + showMessage(`Hello! I'm the Cookiebot, what's your name?`, 'bot'); +}; + +// Start by greeting the user Welcome! +setTimeout(greetUser, 1000); \ No newline at end of file diff --git a/code/style.css b/code/style.css index a275402f..5a0c87a1 100644 --- a/code/style.css +++ b/code/style.css @@ -1,20 +1,22 @@ -* { - box-sizing: border-box; -} - body { - margin: 0; + margin: 2%; padding: 0; font-family: 'Montserrat', sans-serif; - background: #0026ff; + background: rgb(243, 199, 37); + display: flex; + flex-direction: column; + overflow-x: hidden; } h1 { font-weight: bold; - font-size: 28px; + /* font-size: 28px; */ line-height: 34px; color: #fff; text-align: center; + font-family: "Gloria Hallelujah", cursive; + font-weight: 400; + font-style: normal; } h2 { @@ -26,6 +28,12 @@ h2 { margin-bottom: 36px; } +h4 { + font-weight: normal; + margin: 10px 0; + text-align: right; +} + p { font-size: 18px; font-weight: 600; @@ -33,26 +41,42 @@ p { margin: 0; } -input { - box-sizing: border-box; - border: none; - border-radius: 4px 0 0 4px; - background: #e5e9ff; - color: #0026ff; - padding: 16px; - font-size: 16px; - font-family: 'Montserrat'; - font-weight: 600; - line-height: 26px; - flex: 1; - width: 100%; +.welcome-container { + display: flex; + flex-direction: row; +} + +.cookie-message { + width: 50%; +} + +.image-container { + display: flex; + /* Aktivera flexbox för att centrera bilden */ + justify-content: center; + /* Centrera innehållet horisontellt */ + align-items: center; + /* Centrera innehållet vertikalt */ + height: auto; + /* Justera höjden som du vill */ + margin-top: 10px; + /* Lägg till marginal om du vill ha lite utrymme mellan

och bilden */ +} + +.monster-picture { + max-width: 100%; + /* Se till att bilden inte överstiger sin container */ + max-height: 600px; +} + +.monster-picture2 { + display: none; } main { margin: 0 auto; - width: 100%; - max-width: 700px; - height: 600px; + width: 50%; + height: 700px; border-radius: 30px; background: #fff; padding: 20px 24px; @@ -60,6 +84,7 @@ main { box-sizing: border-box; display: flex; flex-direction: column; + overflow-x: hidden; } .chat { @@ -71,6 +96,60 @@ main { padding-bottom: 16px; } +.input-wrapper { + display: flex; + justify-content: center; +} + +.input-wrapper form { + width: 100%; + display: flex; + align-items: center; +} + +input { + box-sizing: border-box; + border: none; + border-radius: 4px 0 0 4px; + background: #e5e9ff; + padding: 16px; + font-size: 16px; + font-family: 'Montserrat'; + font-weight: 600; + line-height: 26px; + flex: 1; + width: 100%; +} + +input[type="text"] { + outline: none; +} + +button { + background-color: #00c3f8; + color: white; + border: none; + border-radius: 4px; + padding: 16px 20px; + margin-right: 4px; + font-size: 16px; + line-height: 26px; + font-family: 'Montserrat'; + font-weight: 500; + cursor: pointer; + transition: all 0.3s ease; +} + +button:hover { + opacity: 0.9; + transition: all 0.2s ease; +} + +.button-container { + display: flex; + justify-content: center; +} + .bot-msg { display: flex; margin: 16px 8px 0 0; @@ -84,67 +163,129 @@ main { flex-shrink: 0; } -.bot-msg img, +.bot-msg img { + width: 60px; + height: 60px; +} + .user-msg img { width: 60px; height: 60px; } .bubble { - background: #e5e9ff; + /* background: #e5e9ff; */ + color: black; font-weight: 600; font-size: 16px; line-height: 26px; padding: 16px 24px; - color: #0026ff; max-width: 40%; } .bot-bubble { + /* background: rgb(223, 223, 223); */ + background: #f5e9be; border-radius: 0px 26px 26px 26px; margin-left: 8px; } .user-bubble { + background: #a2ebff; border-radius: 26px 0 26px 26px; margin-right: 8px; } -.input-wrapper { +footer { + border-top: 4px dotted white; + margin-top: 4%; + color: white; + padding-top: 2%; display: flex; - justify-content: center; + flex-direction: row-reverse; } -.input-wrapper form { - width: 100%; - display: flex; - align-items: center; -} +/* For mobile phones */ +@media (max-width: 667px) { -label { - font-size: 16px; - font-family: 'Montserrat'; - font-weight: 500; - color: #0026ff; - margin-right: 20px; -} + h4 { + font-size: 0.7rem; + } -button { - background-color: #0026ff; - color: white; - border: none; - border-radius: 4px; - padding: 16px 20px; - margin-right: 4px; - font-size: 16px; - line-height: 26px; - font-family: 'Montserrat'; - font-weight: 500; - cursor: pointer; - transition: all 0.3s ease; + .welcome-container { + flex-direction: column; + } + + .cookie-message { + width: 100%; + } + + .monster-picture { + display: none; + } + + .monster-picture2 { + display: block; + width: 100%; + } + + main { + width: 100%; + padding: 0 12px 20px 12px; + height: 500px; + } + + .button-container { + flex-direction: column; + } + + button { + margin-right: 0; + margin-top: 2px; + padding: 10px 20px; + } + + .send-btn { + border-radius: 4px; + padding: 16px 20px; + } + + .bubble p { + font-size: 0.8rem; + } } -button:hover { - opacity: 0.9; - transition: all 0.2s ease; +/* for tablet */ +@media (min-width: 668px) and (max-width: 1024px) { + + body { + margin: 5% 2%; + } + + h1 { + width: 170%; + margin: 4% 0 4% 4%; + } + + .welcome-container { + flex-direction: column; + } + + .cookie-message { + width: 100%; + display: flex; + } + + .monster-picture { + display: none; + } + + .monster-picture2 { + display: block; + width: 50%; + } + + main { + width: 75%; + } } \ No newline at end of file diff --git a/pull_request_template.md b/pull_request_template.md index 70fa177f..6ad3ea19 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1,3 +1,2 @@ ## Netlify link -Add your Netlify link here. -PS. Don't forget to add it in your readme as well. +https://cookiebot-lifeisbetterwithcookies.netlify.app/