Spaces:
Sleeping
Sleeping
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Chef Bot</title> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
margin: 0; | |
padding: 0; | |
background-color: #f0f2f5; | |
overflow-x: hidden; | |
} | |
.chat-container { | |
width: 100%; | |
max-width: 100%; | |
height: 100vh; | |
border: 1px solid #ccc; | |
border-radius: 0; | |
background-color: white; | |
display: flex; | |
flex-direction: column; | |
box-sizing: border-box; | |
} | |
.chat-header { | |
background-color: #0288d1; | |
color: white; | |
padding: 8px; | |
text-align: center; | |
font-size: 16px; | |
flex-shrink: 0; | |
} | |
.chat-messages { | |
flex: 1; | |
overflow-y: auto; | |
padding: 5px; | |
box-sizing: border-box; | |
scroll-behavior: smooth; | |
} | |
.bot-message { | |
background-color: #e3f2fd; | |
padding: 8px; | |
margin: 5px 0; | |
border-radius: 5px; | |
max-width: 85%; | |
word-wrap: break-word; | |
font-size: 12px; | |
} | |
.user-message { | |
background-color: #ffebee; | |
padding: 8px; | |
margin: 5px 0; | |
border-radius: 5px; | |
max-width: 85%; | |
margin-left: auto; | |
text-align: right; | |
word-wrap: break-word; | |
font-size: 12px; | |
} | |
.chat-input { | |
display: flex; | |
padding: 5px; | |
border-top: 1px solid #ccc; | |
flex-shrink: 0; | |
position: fixed; | |
bottom: 0; | |
width: 100%; | |
background-color: white; | |
box-sizing: border-box; | |
} | |
.chat-input input { | |
flex: 1; | |
padding: 6px; | |
border: 1px solid #ccc; | |
border-radius: 5px; | |
font-size: 12px; | |
min-height: 35px; | |
box-sizing: border-box; | |
} | |
.chat-input button { | |
padding: 6px 10px; | |
margin-left: 5px; | |
background-color: #ff8f00; | |
color: white; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
font-size: 12px; | |
min-height: 35px; | |
min-width: 60px; | |
} | |
.chat-input button:active { | |
background-color: #f57c00; | |
} | |
.item-box { | |
background-color: white; | |
border: 1px solid #ddd; | |
border-radius: 6px; | |
padding: 8px; | |
margin: 5px 0; | |
max-width: 200px; | |
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); | |
} | |
.item-image { | |
width: 100%; | |
height: 100px; | |
object-fit: cover; | |
border-radius: 5px; | |
margin-bottom: 5px; | |
} | |
.item-name { | |
font-size: 12px; | |
font-weight: bold; | |
color: #333; | |
margin-bottom: 3px; | |
} | |
.add-button, .submit-button { | |
padding: 4px; | |
background-color: #4caf50; | |
color: white; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
font-size: 10px; | |
width: 100%; | |
margin-top: 5px; | |
} | |
.add-button:active, .submit-button:active { | |
background-color: #45a049; | |
} | |
.options-container { | |
display: flex; | |
flex-wrap: wrap; | |
gap: 5px; | |
margin: 5px 0; | |
} | |
.option-button { | |
padding: 6px 10px; | |
margin: 3px; | |
background-color: #7b1fa2; | |
color: white; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
font-size: 12px; | |
min-width: 60px; | |
} | |
.option-button.green { background-color: #4caf50; } | |
.option-button.red { background-color: #d32f2f; } | |
.option-button:active { opacity: 0.9; } | |
.selection-box { | |
background-color: #e1f5fe; | |
padding: 8px; | |
border: 1px solid #0288d1; | |
border-radius: 5px; | |
margin: 5px 0; | |
font-size: 12px; | |
display: flex; | |
flex-wrap: wrap; | |
align-items: center; | |
gap: 5px; | |
} | |
.manual-input { | |
padding: 4px; | |
border: 1px solid #0288d1; | |
border-radius: 5px; | |
font-size: 12px; | |
width: 100px; | |
} | |
.order-name-input { | |
padding: 4px; | |
border: 1px solid #0288d1; | |
border-radius: 5px; | |
font-size: 12px; | |
width: 100px; | |
} | |
.customized-item { | |
background-color: #bbdefb; | |
padding: 8px; | |
border-radius: 5px; | |
margin: 5px 0; | |
font-size: 12px; | |
} | |
@media (max-width: 480px) { | |
.chat-header { font-size: 14px; padding: 6px; } | |
.chat-messages { padding: 3px; } | |
.bot-message, .user-message { font-size: 11px; padding: 6px; margin: 3px 0; } | |
.chat-input input { font-size: 11px; min-height: 30px; padding: 5px; } | |
.chat-input button { font-size: 11px; min-height: 30px; padding: 5px 8px; min-width: 50px; } | |
.item-box { max-width: 150px; } | |
.item-image { height: 80px; } | |
.item-name { font-size: 10px; } | |
.add-button, .submit-button { font-size: 9px; } | |
.option-button { font-size: 11px; padding: 5px 8px; min-width: 50px; } | |
.selection-box { padding: 6px; gap: 3px; } | |
.manual-input, .order-name-input { width: 80px; font-size: 11px; padding: 3px; } | |
.customized-item { font-size: 11px; } | |
} | |
</style> | |
</head> | |
<body> | |
<div class="chat-container"> | |
<div class="chat-header">🍳 Chef Bot</div> | |
<div class="chat-messages" id="chatMessages"> | |
<div class="bot-message">Hello! I’m Chef Bot, your culinary assistant! What’s your name?</div> | |
</div> | |
<div class="chat-input"> | |
<input type="text" id="userInput" placeholder="Type here (e.g., paneer, chicken)..."> | |
<button onclick="sendMessage()">Send</button> | |
</div> | |
</div> | |
<script> | |
let conversation = [ | |
{ role: 'bot', message: 'Hello! I’m Chef Bot, your culinary assistant! What’s your name?' } | |
]; | |
let selectedItem = null; | |
let customIngredients = []; | |
let selectionBoxVisible = false; | |
function addMessage(role, message) { | |
const chatMessages = document.getElementById('chatMessages'); | |
if (!chatMessages) return; | |
const messageDiv = document.createElement('div'); | |
messageDiv.className = role === 'bot' ? 'bot-message' : 'user-message'; | |
messageDiv.textContent = message; | |
chatMessages.appendChild(messageDiv); | |
chatMessages.scrollTop = chatMessages.scrollHeight; | |
} | |
function sendMessage() { | |
const userInput = document.getElementById('userInput'); | |
if (!userInput) return; | |
const message = userInput.value.trim(); | |
if (message) { | |
addMessage('user', message); | |
conversation.push({ role: 'user', message }); | |
selectionBoxVisible = true; | |
handleResponse(message); | |
} else { | |
addMessage('bot', 'Please type a dish or preference! 😄'); | |
} | |
userInput.value = ''; | |
updateSelectionBox(); | |
} | |
function handleResponse(userInput) { | |
const lowerInput = userInput.toLowerCase(); | |
if (conversation.length === 2) { | |
addMessage('bot', `Hi ${userInput}! 🍳 Choose a dish or preference below!`); | |
displayOptions([ | |
{ text: 'Vegetarian', class: 'green' }, | |
{ text: 'Non-Vegetarian', class: 'red' } | |
]); | |
} else if (lowerInput === 'vegetarian' || lowerInput === 'non-vegetarian') { | |
addMessage('bot', `Fetching ${lowerInput} dish...`); | |
fetchMenuItem(lowerInput); | |
} else { | |
addMessage('bot', `Looking for "${userInput}"...`); | |
fetchMenuItem(null, userInput); | |
} | |
} | |
function displayOptions(options) { | |
const chatMessages = document.getElementById('chatMessages'); | |
if (!chatMessages) return; | |
const optionsDiv = document.createElement('div'); | |
optionsDiv.className = 'options-container'; | |
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 }); | |
handleResponse(opt.text); | |
}; | |
optionsDiv.appendChild(button); | |
}); | |
chatMessages.appendChild(optionsDiv); | |
} | |
function fetchMenuItem(dietaryPreference = '', searchTerm = '') { | |
const payload = {}; | |
if (dietaryPreference) 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', `Error: ${data.error}. Try again!`); | |
} else if (data.menu_items.length > 0) { | |
selectedItem = data.menu_items[0]; // Select the first item | |
addMessage('bot', `Found "${selectedItem.name}"!`); | |
displayItemBox(selectedItem); | |
} else { | |
addMessage('bot', `No matches for "${searchTerm || dietaryPreference}". Try "paneer"!`); | |
} | |
}) | |
.catch(error => { | |
addMessage('bot', `Connection issue: ${error.message}. Retrying...`); | |
setTimeout(() => fetchMenuItem(dietaryPreference, searchTerm), 2000); | |
}); | |
} | |
function displayItemBox(item) { | |
const chatMessages = document.getElementById('chatMessages'); | |
if (!chatMessages) return; | |
const itemBox = document.createElement('div'); | |
itemBox.className = 'item-box'; | |
const img = document.createElement('img'); | |
img.src = item.image_url || 'https://via.placeholder.com/100'; | |
img.alt = item.name; | |
img.className = 'item-image'; | |
itemBox.appendChild(img); | |
const nameDiv = document.createElement('div'); | |
nameDiv.className = 'item-name'; | |
nameDiv.textContent = item.name; | |
itemBox.appendChild(nameDiv); | |
const addButton = document.createElement('button'); | |
addButton.className = 'add-button'; | |
addButton.textContent = 'Select'; | |
addButton.onclick = () => { | |
addMessage('bot', `Selected "${item.name}". Add custom ingredients or submit!`); | |
updateSelectionBox(); | |
}; | |
itemBox.appendChild(addButton); | |
chatMessages.appendChild(itemBox); | |
chatMessages.scrollTop = chatMessages.scrollHeight; | |
} | |
function updateSelectionBox() { | |
const chatMessages = document.getElementById('chatMessages'); | |
if (!chatMessages) return; | |
const existingBox = document.querySelector('.selection-box'); | |
if (existingBox) existingBox.remove(); | |
if (!selectionBoxVisible || !selectedItem) return; | |
const selectionBox = document.createElement('div'); | |
selectionBox.className = 'selection-box'; | |
const label = document.createElement('span'); | |
label.textContent = 'Selected:'; | |
selectionBox.appendChild(label); | |
// Display original item | |
const originalItemDiv = document.createElement('div'); | |
originalItemDiv.className = 'customized-item'; | |
originalItemDiv.textContent = `Original: ${selectedItem.name}`; | |
selectionBox.appendChild(originalItemDiv); | |
// Display customized item with ingredients | |
if (customIngredients.length > 0) { | |
const customItemDiv = document.createElement('div'); | |
customItemDiv.className = 'customized-item'; | |
customItemDiv.textContent = `Customized: ${selectedItem.name} with ${customIngredients.join(', ')}`; | |
selectionBox.appendChild(customItemDiv); | |
} | |
// Input for custom ingredients | |
const ingredientInput = document.createElement('input'); | |
ingredientInput.type = 'text'; | |
ingredientInput.placeholder = 'Add ingredient (e.g., onion)'; | |
ingredientInput.className = 'manual-input'; | |
ingredientInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter' && ingredientInput.value.trim()) { | |
const ingredient = ingredientInput.value.trim(); | |
fetchIngredient(ingredient); | |
ingredientInput.value = ''; | |
} | |
}); | |
selectionBox.appendChild(ingredientInput); | |
// Order name input | |
const orderNameInput = document.createElement('input'); | |
orderNameInput.type = 'text'; | |
orderNameInput.placeholder = 'Order Name'; | |
orderNameInput.className = 'order-name-input'; | |
selectionBox.appendChild(orderNameInput); | |
// Submit button | |
const submitButton = document.createElement('button'); | |
submitButton.className = 'submit-button'; | |
submitButton.textContent = 'Submit'; | |
submitButton.onclick = () => { | |
const customOrderName = orderNameInput.value.trim(); | |
submitToSalesforce(customOrderName); | |
}; | |
selectionBox.appendChild(submitButton); | |
chatMessages.appendChild(selectionBox); | |
chatMessages.scrollTop = chatMessages.scrollHeight; | |
} | |
function fetchIngredient(ingredientName) { | |
fetch('/get_sector_item_details', { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ item_name: ingredientName }) | |
}) | |
.then(response => response.json()) | |
.then(data => { | |
if (data.error) { | |
addMessage('bot', `Ingredient "${ingredientName}" not found. Try another!`); | |
} else { | |
customIngredients.push(data.item_details.name); | |
addMessage('bot', `Added ingredient "${data.item_details.name}" to "${selectedItem.name}"!`); | |
updateSelectionBox(); | |
} | |
}) | |
.catch(error => { | |
addMessage('bot', `Error fetching "${ingredientName}". Retrying...`); | |
setTimeout(() => fetchIngredient(ingredientName), 2000); | |
}); | |
} | |
function submitToSalesforce(customOrderName) { | |
if (!selectedItem) { | |
addMessage('bot', 'No item selected! Please select a dish! 😊'); | |
return; | |
} | |
const order = { | |
name: selectedItem.name, | |
category: selectedItem.category || 'Not specified', | |
description: selectedItem.description || 'No description available', | |
image_url: selectedItem.image_url || '', | |
custom_ingredients: customIngredients, | |
quantity: 1 | |
}; | |
fetch('/submit_items', { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ items: [order], custom_order_name: customOrderName }) | |
}) | |
.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?`); | |
selectedItem = null; | |
customIngredients = []; | |
selectionBoxVisible = false; | |
updateSelectionBox(); | |
} | |
}) | |
.catch(error => { | |
addMessage('bot', `Submission error: ${error.message}. Retrying...`); | |
setTimeout(() => submitToSalesforce(customOrderName), 2000); | |
}); | |
} | |
document.getElementById('userInput').addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') sendMessage(); | |
}); | |
console.log('Chef Bot script loaded!'); | |
</script> | |
</body> | |
</html> |