chatcustomer1111 / templates /chef-bot.html
lokesh341's picture
Update templates/chef-bot.html
90e6c0c verified
raw
history blame
35.7 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chef Bot</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Arial, sans-serif;
background-color: #f4f7fa;
overflow-x: hidden;
line-height: 1.5;
}
.chat-container {
width: 100%;
max-width: 800px;
height: 100vh;
margin: 0 auto;
background-color: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
overflow: hidden;
}
.chat-header {
background-color: #0078d4;
color: #ffffff;
padding: 12px;
text-align: center;
font-size: 18px;
font-weight: 600;
flex-shrink: 0;
}
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 15px;
scroll-behavior: smooth;
}
.bot-message, .user-message {
padding: 10px 15px;
margin: 8px 0;
border-radius: 12px;
max-width: 80%;
font-size: 14px;
line-height: 1.4;
}
.bot-message {
background-color: #e8f0fe;
color: #333;
}
.user-message {
background-color: #0078d4;
color: #ffffff;
margin-left: auto;
}
.chat-input {
display: flex;
padding: 10px;
border-top: 1px solid #e0e0e0;
background-color: #f9f9f9;
flex-shrink: 0;
}
.chat-input input {
flex: 1;
padding: 10px;
border: 1px solid #ccc;
border-radius: 8px;
font-size: 14px;
outline: none;
}
.chat-input button {
padding: 10px 20px;
margin-left: 10px;
background-color: #0078d4;
color: #ffffff;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.2s;
}
.chat-input button:hover {
background-color: #005ea2;
}
.ingredients-list, .menu-items-list, .customization-ingredients-list {
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
padding: 10px;
margin: 10px 0;
background-color: #f5f7fa;
border-radius: 10px;
gap: 15px;
scroll-behavior: smooth;
}
.ingredient-item, .menu-item {
flex: 0 0 200px;
background-color: #ffffff;
border: 1px solid #e0e0e0;
border-radius: 10px;
padding: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
transition: transform 0.2s;
text-align: center;
}
.ingredient-item:hover, .menu-item:hover {
transform: translateY(-2px);
}
.ingredient-item img, .menu-item img {
width: 100%;
height: 120px;
object-fit: cover;
border-radius: 8px;
margin-bottom: 8px;
}
.ingredient-item div, .menu-item div {
font-size: 14px;
font-weight: 600;
color: #333;
margin-bottom: 5px;
}
.ingredient-item button, .menu-item button {
padding: 8px;
background-color: #28a745;
color: #ffffff;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
width: 100%;
}
.ingredient-item button:hover, .menu-item button:hover {
background-color: #218838;
}
.selected-ingredients {
background-color: #f1f8ff;
padding: 15px;
border: 1px solid #b3d7ff;
border-radius: 10px;
margin: 10px 0;
font-size: 14px;
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.selected-ingredients div {
background-color: #d6e9ff;
padding: 5px 10px;
border-radius: 6px;
font-size: 13px;
}
.customization-input {
margin: 10px 0;
}
.customization-input textarea {
width: 100%;
padding: 8px;
border: 1px solid #b3d7ff;
border-radius: 6px;
font-size: 14px;
outline: none;
margin-bottom: 10px;
}
.customization-input button, .submit-button {
padding: 10px 20px;
background-color: #0078d4;
color: #ffffff;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.2s;
}
.customization-input button:hover, .submit-button:hover {
background-color: #005ea2;
}
.option-button {
padding: 10px 20px;
color: #ffffff;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
margin: 5px;
transition: background-color 0.2s;
}
.option-button.green {
background-color: #28a745;
}
.option-button.green:hover {
background-color: #218838;
}
.option-button.red {
background-color: #dc3545;
}
.option-button.red:hover {
background-color: #c82333;
}
.cart-items {
background-color: #f1f8ff;
padding: 15px;
border: 1px solid #b3d7ff;
border-radius: 10px;
margin: 10px 0;
font-size: 14px;
}
.cart-item {
display: flex;
align-items: center;
background-color: #d6e9ff;
padding: 5px 10px;
border-radius: 6px;
font-size: 13px;
margin: 5px 0;
}
.cart-item img {
width: 30px;
height: 30px;
object-fit: cover;
border-radius: 6px;
margin-right: 8px;
}
.cart-item .remove-button {
padding: 5px 10px;
margin-left: 8px;
background-color: #dc3545;
color: #ffffff;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
}
.cart-item .remove-button:hover {
background-color: #c82333;
}
.cart-item .ingredient-info-input {
padding: 8px;
border: 1px solid #b3d7ff;
border-radius: 6px;
font-size: 13px;
width: 150px;
outline: none;
margin: 5px;
}
.submit-cart {
margin: 10px 0;
}
.submit-cart input {
padding: 8px;
border: 1px solid #b3d7ff;
border-radius: 6px;
font-size: 14px;
margin-right: 10px;
}
.quantity-input {
width: 60px;
}
/* Responsive Design */
@media (max-width: 480px) {
.chat-container {
border-radius: 0;
box-shadow: none;
}
.chat-header {
font-size: 16px;
padding: 10px;
}
.chat-messages {
padding: 10px;
}
.bot-message, .user-message {
font-size: 13px;
padding: 8px 12px;
margin: 5px 0;
}
.chat-input input {
font-size: 13px;
padding: 8px;
}
.chat-input button {
font-size: 13px;
padding: 8px 15px;
}
.ingredients-list, .menu-items-list, .customization-ingredients-list {
flex-direction: column;
gap: 10px;
padding: 8px;
}
.ingredient-item, .menu-item {
flex: 0 0 auto;
width: 100%;
max-width: 250px;
}
.ingredient-item img, .menu-item img {
height: 100px;
}
.ingredient-item div, .menu-item div {
font-size: 13px;
}
.ingredient-item button, .menu-item button {
font-size: 11px;
padding: 6px;
}
.option-button {
font-size: 13px;
padding: 8px 15px;
}
.selected-ingredients, .cart-items {
padding: 10px;
gap: 8px;
}
.cart-item {
font-size: 12px;
padding: 4px 8px;
}
.cart-item img {
width: 25px;
height: 25px;
}
.cart-item .ingredient-info-input {
width: 120px;
font-size: 12px;
}
.submit-cart input {
width: 120px;
font-size: 13px;
padding: 6px;
}
.quantity-input {
width: 50px;
}
.submit-button {
font-size: 13px;
padding: 8px 15px;
}
.cart-item .remove-button {
font-size: 11px;
padding: 4px 8px;
}
}
@media (min-width: 481px) and (max-width: 768px) {
.chat-container {
max-width: 600px;
}
.chat-header {
font-size: 17px;
padding: 11px;
}
.chat-messages {
padding: 12px;
}
.ingredient-item, .menu-item {
flex: 0 0 180px;
}
.ingredient-item img, .menu-item img {
height: 110px;
}
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-header">🍳 Chef Bot</div>
<div class="chat-messages" id="chatMessages">
<div class="bot-message">Hi there! I'm Chef Bot! May I know your name?</div>
</div>
<div class="chat-input">
<input type="text" id="userInput" placeholder="Type your name or message...">
<button onclick="sendMessage()">Send</button>
</div>
</div>
<script>
let conversation = [
{ role: 'bot', message: "Hi there! I'm Chef Bot! May I know your name?" }
];
let userName = '';
let selectedPreference = '';
let selectedIngredients = [];
let selectedMenuItem = null;
let cart = [];
function addMessage(role, message) {
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('Chat messages container not found!');
return;
}
const messageDiv = document.createElement('div');
messageDiv.className = role === 'bot' ? 'bot-message' : 'user-message';
messageDiv.textContent = message;
chatMessages.appendChild(messageDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
console.log(`Added ${role} message: ${message}`);
}
function sendMessage() {
const userInput = document.getElementById('userInput');
if (!userInput) {
console.error('User input field not found!');
return;
}
const message = userInput.value.trim();
if (message) {
addMessage('user', message);
conversation.push({ role: 'user', message: message });
userInput.value = '';
setTimeout(() => handleResponse(message), 500);
} else {
addMessage('bot', 'Please type something! 😄');
console.warn('Empty message!');
}
updateCartDisplay();
}
function handleResponse(userInput) {
const lastMessage = userInput.toLowerCase();
let botResponse = '';
let options = [];
if (!userName) { // Name input
userName = userInput;
botResponse = `Nice to meet you, ${userName}! 😊 Let's create your perfect meal! What type of food would you prefer?`;
options = [
{ text: 'Vegetarian', class: 'green' },
{ text: 'Non-Vegetarian', class: 'red' }
];
} else if (!selectedPreference && (lastMessage.includes('vegetarian') || lastMessage.includes('non-vegetarian'))) {
selectedPreference = lastMessage.includes('vegetarian') ? 'vegetarian' : 'non-vegetarian';
conversation.push({ role: 'user', message: selectedPreference.charAt(0).toUpperCase() + selectedPreference.slice(1) });
console.log(`Food preference selected: ${selectedPreference}`);
botResponse = `Great choice! 🍽️ Here are some ingredients:`;
fetchIngredients();
return;
} else if (lastMessage.includes('yes') && selectedMenuItem) {
botResponse = 'Awesome! Let’s customize your dish. Here are some ingredients you can add:';
fetchCustomizationIngredients('both');
return;
} else if (lastMessage.includes('no') && selectedMenuItem) {
addToCart(selectedMenuItem);
botResponse = 'Item added to cart! Would you like to order more?';
options = [
{ text: 'Yes', class: 'green' },
{ text: 'No', class: 'red' }
];
selectedMenuItem = null;
selectedIngredients = [];
} else {
botResponse = `Searching for "${userInput}"...`;
fetchMenuItems(selectedPreference, userInput);
return;
}
addMessage('bot', botResponse);
if (options.length > 0) {
displayOptions(options);
}
updateCartDisplay();
}
function fetchIngredients() {
fetch('/get_ingredients', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ dietary_preference: 'both' })
})
.then(response => response.json())
.then(data => {
if (data.error) {
addMessage('bot', `Sorry, there was an error fetching ingredients: ${data.error}`);
} else {
const ingredients = data.ingredients || [];
addMessage('bot', 'Please select ingredients:');
displayIngredientsList(ingredients);
}
})
.catch(error => {
addMessage('bot', `Error: Unable to connect to the ingredient database. ${error.message}`);
});
}
function fetchCustomizationIngredients(foodPreference) {
fetch('/get_ingredients', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ dietary_preference: foodPreference })
})
.then(response => response.json())
.then(data => {
if (data.error) {
addMessage('bot', `Sorry, there was an error fetching customization ingredients: ${data.error}`);
} else {
const ingredients = data.ingredients || [];
addMessage('bot', 'Select ingredients to customize your dish:');
displayCustomizationIngredients(ingredients);
displaySelectedIngredientsForCustomization();
displayCustomizationInput();
}
})
.catch(error => {
addMessage('bot', `Error: Unable to connect to the ingredient database. ${error.message}`);
});
}
function fetchMenuItems(dietaryPreference, searchTerm = '') {
const payload = { dietary_preference: dietaryPreference };
if (searchTerm) payload.search_term = searchTerm;
fetch('/get_menu_items', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => {
if (data.error) {
addMessage('bot', `Sorry, there was an error fetching menu items: ${data.error}`);
} else if (data.menu_items.length > 0) {
addMessage('bot', `--- Found ${data.menu_items.length} item${data.menu_items.length > 1 ? 's' : ''} ---`);
displayMenuItems(data.menu_items);
} else {
addMessage('bot', `No matches for "${searchTerm || dietaryPreference}". Try "paneer"!`);
}
})
.catch(error => {
addMessage('bot', `Error: Unable to connect to the menu database. ${error.message}`);
});
}
function fetchRelatedMenuItems(ingredientName) {
fetch('/get_related_menu_items', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ingredient_name: ingredientName, dietary_preference: selectedPreference })
})
.then(response => response.json())
.then(data => {
if (data.error) {
addMessage('bot', `Error: ${data.error}. Try another ingredient!`);
} else if (data.menu_items.length > 0) {
addMessage('bot', `--- Found ${data.menu_items.length} dish${data.menu_items.length > 1 ? 'es' : ''} with "${ingredientName}" ---`);
displayMenuItems(data.menu_items);
} else {
addMessage('bot', `No dishes found with "${ingredientName}". Try another!`);
}
})
.catch(error => {
addMessage('bot', `Error: Unable to connect to the menu database. ${error.message}`);
});
}
function displayIngredientsList(ingredients) {
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('Chat messages container not found for ingredients!');
return;
}
let ingredientsList = document.querySelector('.ingredients-list');
if (!ingredientsList) {
ingredientsList = document.createElement('div');
ingredientsList.className = 'ingredients-list';
chatMessages.appendChild(ingredientsList);
} else {
ingredientsList.innerHTML = '';
}
ingredients.forEach(ingredient => {
const item = document.createElement('div');
item.className = 'ingredient-item';
const img = document.createElement('img');
img.src = ingredient.image_url || 'https://via.placeholder.com/120';
img.alt = ingredient.name;
const name = document.createElement('div');
name.textContent = ingredient.name;
const button = document.createElement('button');
button.textContent = 'Select';
button.onclick = () => {
addMessage('bot', `Finding dishes with "${ingredient.name}"...`);
fetchRelatedMenuItems(ingredient.name);
};
item.appendChild(img);
item.appendChild(name);
item.appendChild(button);
ingredientsList.appendChild(item);
});
}
function displayCustomizationIngredients(ingredients) {
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('Chat messages container not found for customization ingredients!');
return;
}
let ingredientsList = document.querySelector('.customization-ingredients-list');
if (!ingredientsList) {
ingredientsList = document.createElement('div');
ingredientsList.className = 'customization-ingredients-list';
chatMessages.appendChild(ingredientsList);
} else {
ingredientsList.innerHTML = '';
}
ingredients.forEach(ingredient => {
const item = document.createElement('div');
item.className = 'ingredient-item';
const img = document.createElement('img');
img.src = ingredient.image_url || 'https://via.placeholder.com/120';
img.alt = ingredient.name;
const name = document.createElement('div');
name.textContent = ingredient.name;
const button = document.createElement('button');
button.textContent = 'Add';
button.onclick = () => {
if (!selectedIngredients.some(item => item.name === ingredient.name)) {
selectedIngredients.push(ingredient);
displaySelectedIngredientsForCustomization();
}
};
item.appendChild(img);
item.appendChild(name);
item.appendChild(button);
ingredientsList.appendChild(item);
});
}
function displaySelectedIngredientsForCustomization() {
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('Chat messages container not found for selected ingredients!');
return;
}
let selectedArea = document.querySelector('.selected-ingredients');
if (!selectedArea) {
selectedArea = document.createElement('div');
selectedArea.className = 'selected-ingredients';
chatMessages.appendChild(selectedArea);
} else {
selectedArea.innerHTML = '';
}
selectedIngredients.forEach(ingredient => {
const div = document.createElement('div');
div.textContent = ingredient.name;
selectedArea.appendChild(div);
});
}
function displayMenuItems(menuItems) {
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('Chat messages container not found for menu items!');
return;
}
let menuItemsList = document.querySelector('.menu-items-list');
if (!menuItemsList) {
menuItemsList = document.createElement('div');
menuItemsList.className = 'menu-items-list';
chatMessages.appendChild(menuItemsList);
} else {
menuItemsList.innerHTML = '';
}
menuItems.forEach(item => {
const menuItem = document.createElement('div');
menuItem.className = 'menu-item';
const img = document.createElement('img');
img.src = item.image_url || 'https://via.placeholder.com/120';
img.alt = item.name;
const name = document.createElement('div');
name.textContent = item.name;
const button = document.createElement('button');
button.textContent = 'Add to Cart';
button.onclick = () => {
selectedMenuItem = item;
addMessage('bot', `World-class selection! Would you like to customize your dish further?`);
const options = [
{ text: 'Yes', class: 'green' },
{ text: 'No', class: 'red' }
];
displayOptions(options);
};
menuItem.appendChild(img);
menuItem.appendChild(name);
menuItem.appendChild(button);
menuItemsList.appendChild(menuItem);
});
}
function displayCustomizationInput() {
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('Chat messages container not found for customization input!');
return;
}
let customizationArea = document.querySelector('.customization-input');
if (!customizationArea) {
customizationArea = document.createElement('div');
customizationArea.className = 'customization-input';
const textarea = document.createElement('textarea');
textarea.placeholder = 'Enter any special instructions...';
const submitButton = document.createElement('button');
submitButton.textContent = 'Submit Instructions';
submitButton.onclick = () => {
const instructions = textarea.value.trim();
addToCart({ ...selectedMenuItem, instructions, ingredients: selectedIngredients });
addMessage('bot', 'Item added to cart! Would you like to order more?');
const options = [
{ text: 'Yes', class: 'green' },
{ text: 'No', class: 'red' }
];
displayOptions(options);
selectedMenuItem = null;
selectedIngredients = [];
updateCartDisplay();
};
customizationArea.appendChild(textarea);
customizationArea.appendChild(submitButton);
chatMessages.appendChild(customizationArea);
}
}
function addToCart(item) {
const cartItem = {
name: item.name,
image_url: item.image_url || '',
category: item.veg_nonveg || 'Not specified',
description: item.description || 'No description available',
instructions: item.instructions || '',
ingredients: item.ingredients || [],
quantity: 1,
ingredientsInfo: ''
};
cart.push(cartItem);
console.log('Cart:', cart);
updateCartDisplay();
}
function updateCartDisplay() {
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) return;
let cartArea = document.querySelector('.cart-items');
if (!cartArea) {
cartArea = document.createElement('div');
cartArea.className = 'cart-items';
chatMessages.appendChild(cartArea);
} else {
cartArea.innerHTML = '';
}
if (cart.length > 0) {
const label = document.createElement('div');
label.textContent = 'Cart:';
cartArea.appendChild(label);
cart.forEach((item, index) => {
const itemDiv = document.createElement('div');
itemDiv.className = 'cart-item';
const img = document.createElement('img');
img.src = item.image_url || 'https://via.placeholder.com/30';
img.alt = item.name;
itemDiv.appendChild(img);
const contentDiv = document.createElement('div');
const itemText = item.instructions
? `${item.name} (${item.instructions})`
: item.name;
contentDiv.textContent = `${itemText} (Qty: ${item.quantity})`;
if (item.ingredients.length > 0) {
contentDiv.textContent += ` with ${item.ingredients.map(i => i.name).join(', ')}`;
}
itemDiv.appendChild(contentDiv);
const infoInput = document.createElement('input');
infoInput.type = 'text';
infoInput.placeholder = 'Add ingredient details...';
infoInput.className = 'ingredient-info-input';
infoInput.value = item.ingredientsInfo || '';
infoInput.addEventListener('input', (e) => {
cart[index].ingredientsInfo = e.target.value;
});
itemDiv.appendChild(infoInput);
const removeButton = document.createElement('button');
removeButton.textContent = 'X';
removeButton.className = 'remove-button';
removeButton.onclick = () => {
cart.splice(index, 1);
addMessage('bot', `Removed "${item.name}" from cart.`);
updateCartDisplay();
};
itemDiv.appendChild(removeButton);
cartArea.appendChild(itemDiv);
});
let submitArea = document.querySelector('.submit-cart');
if (!submitArea) {
submitArea = document.createElement('div');
submitArea.className = 'submit-cart';
const orderNameInput = document.createElement('input');
orderNameInput.type = 'text';
orderNameInput.placeholder = 'Order Name';
orderNameInput.className = 'order-name-input';
const quantityInput = document.createElement('input');
quantityInput.type = 'number';
quantityInput.min = '1';
quantityInput.value = '1';
quantityInput.className = 'quantity-input';
const submitButton = document.createElement('button');
submitButton.textContent = 'Submit Cart';
submitButton.className = 'submit-button';
submitButton.onclick = () => {
submitCart(orderNameInput.value, quantityInput.value);
};
submitArea.appendChild(orderNameInput);
submitArea.appendChild(quantityInput);
submitArea.appendChild(submitButton);
chatMessages.appendChild(submitArea);
}
}
chatMessages.scrollTop = chatMessages.scrollHeight;
}
function submitCart(customOrderName, quantity) {
if (cart.length === 0) {
addMessage('bot', 'No items in cart! Add some dishes! 😊');
return;
}
if (confirm(`Submit ${cart.length} items (Qty: ${quantity}) as- const itemsToSubmit = cart.map(item => ({
name: item.name,
category: item.category,
description: item.description,
image_url: item.image_url,
quantity: parseInt(quantity) || 1,
instructions: item.instructions,
ingredients: item.ingredients,
ingredientsInfo: item.ingredientsInfo
}));
fetch('/submit_ingredients', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
items: itemsToSubmit,
custom_order_name: customOrderName,
ingredients_info: ''
})
})
.then(response => response.json())
.then(data => {
if (data.error) {
addMessage('bot', `Submission failed: ${data.error}. Try again?`);
} else {
addMessage('bot', `Submitted ${data.ingredient_name}! What's next?`);
cart = [];
selectedIngredients = [];
selectedMenuItem = null;
updateCartDisplay();
}
})
.catch(error => {
addMessage('bot', `Submission error: ${error.message}. Retrying...`);
setTimeout(() => submitCart(customOrderName, quantity), 2000);
});
}
function displayOptions(options) {
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages) {
console.error('Chat messages container not found for options!');
return;
}
options.forEach(opt => {
const button = document.createElement('button');
button.textContent = opt.text;
button.className = `option-button ${opt.class}`;
button.onclick = () => {
addMessage('user', opt.text);
conversation.push({ role: 'user', message: opt.text });
setTimeout(() => handleResponse(opt.text), 500);
};
chatMessages.appendChild(button);
});
chatMessages.appendChild(document.createElement('br'));
const backButton = document.createElement('button');
backButton.textContent = 'Go Back';
backButton.className = 'option-button';
backButton.onclick = () => {
conversation.pop();
selectedIngredients = [];
selectedMenuItem = null;
setTimeout(() => handleResponse(conversation[conversation.length - 1].message), 500);
};
chatMessages.appendChild(backButton);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
document.getElementById('userInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendMessage();
}
});
console.log('Script loaded successfully');
</script>
</body>
</html>