-
Notifications
You must be signed in to change notification settings - Fork 411
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
Holiday bot #290
base: main
Are you sure you want to change the base?
Holiday bot #290
Changes from all commits
bcc71aa
1cd6c04
35cb257
0dc3cb4
6f5f534
a40bdff
7789124
546cef8
110f0f9
36ed67e
a178fef
dcda4d6
e44b803
b82523f
27fac67
fd2dc4b
d322e73
7172414
f6ac953
ac1e71b
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,11 @@ | ||
# 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. | ||
A simple chatbot that interacts with the user and guides them through a fun, personalized conversation. | ||
|
||
## 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? | ||
The problem was approached by breaking down the interaction flow into distinct steps: greeting the user, capturing inputs, and generating responses based on the input. Vanilla JavaScript was used for DOM manipulation and event handling, such as form submission. The UI was dynamically updated. Given more time, additional conversation options and design improvements would be implemented to enhance user experience. | ||
|
||
## 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://holiday-bot.netlify.app/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,32 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<link rel="stylesheet" href="./style.css" /> | ||
<link | ||
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" | ||
rel="stylesheet" /> | ||
<title>Chatbot</title> | ||
rel="stylesheet" | ||
/> | ||
<!-- h1 font --> | ||
<link | ||
href="https://fonts.googleapis.com/css2?family=Great+Vibes&display=swap" | ||
rel="stylesheet" | ||
/> | ||
<title>Holiday bot</title> | ||
</head> | ||
|
||
<body> | ||
<h1>Welcome to my chatbot!</h1> | ||
<h1>Holiday bot</h1> | ||
|
||
<main> | ||
<section class="chat" id="chat"></section> | ||
<div class="input-wrapper" id="input-wrapper"> | ||
<form id="name-form"> | ||
<label for="name-input">Name</label> | ||
<input id="name-input" type="text" /> | ||
<button class="send-btn" type="submit"> | ||
Send | ||
</button> | ||
<button class="send-btn" id="send" type="submit">Send</button> | ||
</form> | ||
</div> | ||
</main> | ||
|
||
<script src="./script.js"></script> | ||
</body> | ||
|
||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,267 @@ | ||
// DOM selectors (variables that point to selected DOM elements) goes here 👇 | ||
const chat = document.getElementById('chat') | ||
// DOM selectors (variables that point to selected DOM elements) goes here | ||
const chat = document.getElementById("chat"); | ||
const nameInput = document.getElementById("name-input"); | ||
const form = document.getElementById("name-form"); | ||
const submit = document.getElementById("send"); | ||
const inputWrapper = document.getElementById("input-wrapper"); | ||
|
||
// Functions goes here 👇 | ||
// Variables | ||
let questionNumber = 1; | ||
let userName = ""; | ||
|
||
// Destinations mapped by mood | ||
// Based on the mood selected by the user, the bot will suggest destinations | ||
const destinationsByMood = { | ||
Adventure: ["🏔️ Mount Everest", "🌳 Amazon Rainforest", "🏜️ Sahara Desert"], | ||
Relax: ["🛳️ Maldives", "🌴 Bora Bora", "🏖️ Bali"], | ||
Cultural: ["🍝 Italy", "🏺 Greece", "🍣 Japan"], | ||
Romantic: ["🌹 Paris", "🌅 Venice", "🌺 Santorini"], | ||
}; | ||
|
||
// Function for bot to reply with a message after a delay | ||
// The delay is used to make the conversation feel more natural. | ||
const botReply = (msg) => { | ||
setTimeout(() => showMessage(msg, "bot"), 500); | ||
}; | ||
const userReply = (msg) => { | ||
showMessage(msg, "user"); | ||
}; | ||
Comment on lines
+23
to
+28
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. Nice ⭐ |
||
|
||
// A function that will add a chat bubble in the correct place based on who the sender is | ||
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') { | ||
if (sender === "user") { | ||
chat.innerHTML += ` | ||
<section class="user-msg"> | ||
<div class="bubble user-bubble"> | ||
<p>${message}</p> | ||
</div> | ||
<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 | ||
} else if (sender === 'bot') { | ||
`; | ||
} else if (sender === "bot") { | ||
console.log("Bot message is being shown:", message); // This will log when the bot sends a message | ||
chat.innerHTML += ` | ||
<section class="bot-msg"> | ||
<img src="assets/bot.png" alt="Bot" /> | ||
<div class="bubble bot-bubble"> | ||
<p>${message}</p> | ||
</div> | ||
</section> | ||
` | ||
`; | ||
} | ||
|
||
// 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 | ||
} | ||
chat.scrollTop = chat.scrollHeight; | ||
}; | ||
|
||
// 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 | ||
} | ||
|
||
// 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) | ||
const greeting = () => { | ||
botReply( | ||
`Hi there! I'm your travel assistant, ready to help you pick the perfect destination.` | ||
); | ||
botReply(`Before we start, can I get your name?`); | ||
|
||
// Show the name input field | ||
inputWrapper.innerHTML = ` | ||
<input id="name-input" type="text" placeholder="Enter your name..." /> | ||
<button id="submit-name">Submit</button> | ||
`; | ||
|
||
document | ||
.getElementById("submit-name") | ||
.addEventListener("click", () => handleNameInput()); | ||
}; | ||
|
||
// Handle name input | ||
const handleNameInput = () => { | ||
const nameInput = document.getElementById("name-input"); | ||
userName = nameInput.value.trim(); // Get the user's name | ||
|
||
if (userName) { | ||
userReply(userName); | ||
botReply( | ||
`Nice to meet you, ${userName}! Let's figure out what kind of trip you're in the mood for.` | ||
); | ||
|
||
showMoodOptions(); // Proceed to mood selection | ||
} else { | ||
botReply(`Oops, I didn't catch that! Please enter your name to continue.`); | ||
} | ||
}; | ||
|
||
const showMoodOptions = () => { | ||
// Wait for the bot's message to be displayed first | ||
setTimeout(() => { | ||
inputWrapper.innerHTML = ` | ||
<select id="moodSelect"> | ||
<option value="" selected disabled>👇 Select a mood...</option> | ||
<option value="Adventure">🌍 Adventure</option> | ||
<option value="Relax">🌴 Relax</option> | ||
<option value="Cultural">🏛️ Cultural</option> | ||
<option value="Romantic">💖 Romantic</option> | ||
</select> | ||
`; | ||
|
||
document | ||
.getElementById("moodSelect") | ||
.addEventListener("change", (event) => nextQuestion(event.target.value)); | ||
}, 600); // 500ms delay | ||
}; | ||
|
||
// Proceed to the next question based on the selected mood | ||
const nextQuestion = (mood) => { | ||
botReply(`${mood}, exciting! Let's see which destinations match your mood.`); | ||
|
||
showDestinationOptions(mood); // Pass the mood to showDestinationOptions | ||
}; | ||
|
||
const showDestinationOptions = (mood) => { | ||
const destinations = destinationsByMood[mood]; | ||
|
||
// Wait for the bot's message to be displayed first | ||
setTimeout(() => { | ||
inputWrapper.innerHTML = ` | ||
<select id="select"> | ||
<option value="" selected disabled>👇 Select a destination...</option> | ||
${destinations | ||
.map( | ||
(destination) => | ||
`<option value="${destination}">${destination}</option>` | ||
) | ||
.join("")} | ||
</select> | ||
`; | ||
|
||
const select = document.getElementById("select"); | ||
select.addEventListener("change", () => showMenu(select.value)); | ||
}, 600); // 500ms delay | ||
}; | ||
|
||
// Ask about activities after selecting a destination | ||
const showMenu = (destination) => { | ||
questionNumber++; | ||
|
||
botReply( | ||
`Great choice! ${destination} sounds like an amazing place. Would you like to plan some activities while you're there?` | ||
); | ||
|
||
// Delay the appearance of the Yes/No buttons | ||
setTimeout(() => { | ||
inputWrapper.innerHTML = ` | ||
<button id="theEnd">NO</button> | ||
<button id="confirm">YES</button> | ||
`; | ||
|
||
document.getElementById("theEnd").addEventListener("click", () => { | ||
botReply("Alright, enjoy your trip!"); | ||
inputWrapper.innerHTML = ``; | ||
showStartOverButton(); // Show the "Start Over" button | ||
}); | ||
|
||
document.getElementById("confirm").addEventListener("click", () => { | ||
showActivities(); | ||
}); | ||
}, 600); // Delay of 600ms | ||
}; | ||
|
||
const showActivities = () => { | ||
questionNumber++; | ||
|
||
botReply(`Awesome! What activities would you like to do while you're there?`); | ||
|
||
// Create a dropdown menu for activities | ||
setTimeout(() => { | ||
inputWrapper.innerHTML = ` | ||
<select id="activitySelect"> | ||
<option value="" selected disabled>👇 Select an activity...</option> | ||
<option value="Hiking">🥾 Hiking</option> | ||
<option value="Beach">🏖️ Beach</option> | ||
<option value="Sightseeing">🗺️ Sightseeing</option> | ||
</select> | ||
`; | ||
|
||
document | ||
.getElementById("activitySelect") | ||
.addEventListener("change", (event) => { | ||
const selectedActivity = event.target.value; | ||
if (selectedActivity) { | ||
showChoice(selectedActivity); | ||
} | ||
}); | ||
}, 600); // 500ms delay | ||
}; | ||
|
||
// Show the choice made by the user and prompt readiness | ||
const showChoice = (choice) => { | ||
questionNumber++; | ||
|
||
botReply(`${choice} sounds fun! Are you ready to start planning your trip?`); | ||
|
||
// Add suggestions based on the selected activity | ||
let suggestions = ""; | ||
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. nice!! |
||
if (choice === "Hiking") { | ||
suggestions = ` | ||
Here are some hiking tips and guides: | ||
<ul> | ||
<li><a href="random url" target="_blank">AllTrails - Discover Hiking</a></li> | ||
<li><a href="random url" target="_blank">Hiking for Beginners</a></li> | ||
<li><a href="random url" target="_blank">Top Hiking Trails</a></li> | ||
</ul> | ||
`; | ||
} else if (choice === "Beach") { | ||
suggestions = ` | ||
Here are some beach travel ideas: | ||
<ul> | ||
<li><a href="random url" target="_blank">TripAdvisor - Must-Visit Beaches</a></li> | ||
<li><a href="random url" target="_blank">Condé Nast Traveler - Top Beaches</a></li> | ||
<li><a href="random url" target="_blank">Top 5 Beaches</a></li> | ||
</ul> | ||
`; | ||
} else if (choice === "Sightseeing") { | ||
suggestions = ` | ||
Here are some sightseeing guides: | ||
<ul> | ||
<li><a href="random url" target="_blank">Lonely Planet - Best Sightseeing Tours</a></li> | ||
<li><a href="random url" target="_blank">BuzzFeed - Top Bucket List Sights</a></li> | ||
<li><a href="random url" target="_blank">Rough Guides - Best in Travel 2024</a></li> | ||
</ul> | ||
`; | ||
} | ||
|
||
// Display the suggestions before asking if they're ready | ||
botReply(suggestions); | ||
|
||
// Delay the appearance of the "Ready" button | ||
setTimeout(() => { | ||
inputWrapper.innerHTML = ` | ||
<button id="ready">Ready</button> | ||
`; | ||
|
||
document.getElementById("ready").addEventListener("click", () => { | ||
thankYou(); | ||
}); | ||
}, 600); // Delay of 500ms | ||
}; | ||
|
||
// End of conversation | ||
const thankYou = () => { | ||
botReply( | ||
`Wishing you an incredible trip ${userName}! Hope you have an amazing adventure.` | ||
); | ||
inputWrapper.innerHTML = ``; // Clear input, removes the "ready" btn | ||
showStartOverButton(); // Show the "Start Over" button | ||
}; | ||
|
||
// Show the "Start Over" button after the conversation ends | ||
const showStartOverButton = () => { | ||
setTimeout(() => { | ||
inputWrapper.innerHTML = ` | ||
<button id="start-over">Start Over</button> | ||
`; | ||
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. Loved this! |
||
|
||
document | ||
.getElementById("start-over") | ||
.addEventListener("click", () => location.reload()); | ||
}, 600); // 500ms delay | ||
}; | ||
|
||
// Initiate the conversation | ||
greeting(); |
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.
Really good idea to keep track of the flow ⭐