Spaces:
Sleeping
Sleeping
File size: 8,507 Bytes
7547860 d5ed968 95ee9b6 a2d8fd3 d5ed968 a2d8fd3 d5ed968 95ee9b6 a2d8fd3 95ee9b6 a2d8fd3 d5ed968 95ee9b6 d5ed968 95ee9b6 d5ed968 95ee9b6 d5ed968 95ee9b6 d5ed968 216610c d5ed968 7547860 d5ed968 bcde189 95ee9b6 216610c a2d8fd3 216610c 7547860 758c9f3 a2d8fd3 758c9f3 a2d8fd3 758c9f3 92deae9 758c9f3 a2d8fd3 758c9f3 a2d8fd3 758c9f3 92deae9 a2d8fd3 758c9f3 a2d8fd3 758c9f3 a2d8fd3 758c9f3 a2d8fd3 758c9f3 a2d8fd3 758c9f3 a2d8fd3 758c9f3 a2d8fd3 758c9f3 a2d8fd3 758c9f3 92deae9 a2d8fd3 758c9f3 a2d8fd3 758c9f3 bcde189 758c9f3 d5ed968 7547860 ae7981b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Dining Assistant</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f9;
text-align: center;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
text-align: center;
background-color: #fff;
padding: 40px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
width: 80%;
max-width: 600px;
}
h1 {
color: #333;
}
.mic-button {
width: 80px;
height: 80px;
border-radius: 50%;
background-color: #007bff;
color: white;
font-size: 40px;
border: none;
cursor: pointer;
}
.status {
margin-top: 20px;
font-size: 1.2rem;
color: #555;
}
.menu-items-container {
margin-top: 30px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.menu-item {
background-color: #f9f9f9;
padding: 20px;
border-radius: 10px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
text-align: left;
}
</style>
</head>
<body>
<div class="container">
<h1>AI Dining Assistant</h1>
<button class="mic-button" id="mic-button">🎤</button>
<div class="status" id="status">Press the mic button to start...</div>
<div class="menu-items-container" id="menu-items">
<!-- Menu items will be populated here dynamically -->
</div>
</div>
<script>
const micButton = document.getElementById('mic-button');
const status = document.getElementById('status');
const menuItemsContainer = document.getElementById('menu-items');
let isListening = false;
let selectedItem = '';
let quantity = 0;
micButton.addEventListener('click', () => {
if (!isListening) {
isListening = true;
greetUser();
}
});
// Greet user
function greetUser() {
const utterance = new SpeechSynthesisUtterance("Hi, welcome to Biryani Hub! Can I know your name so I can greet you personally?");
speechSynthesis.speak(utterance);
utterance.onend = () => {
status.textContent = "Listening for your name...";
startListeningForName();
};
}
// Start listening for user input (name)
async function startListeningForName() {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream, { mimeType: "audio/webm;codecs=opus" });
const audioChunks = [];
mediaRecorder.ondataavailable = (event) => audioChunks.push(event.data);
mediaRecorder.onstop = async () => {
const audioBlob = new Blob(audioChunks, { type: "audio/webm" });
const formData = new FormData();
formData.append("audio", audioBlob);
status.textContent = "Processing your name... Please wait.";
try {
const result = await fetch("/process-audio", { method: "POST", body: formData });
const data = await result.json();
selectedItem = data.name;
status.textContent = `Hello ${selectedItem}! How can I help you today?`;
suggestFood();
} catch (error) {
status.textContent = "Sorry, I couldn’t understand that. Could you please repeat?";
isListening = false;
}
};
mediaRecorder.start();
setTimeout(() => mediaRecorder.stop(), 5000); // Stop recording after 5 seconds
}
// Suggest food items to the user
function suggestFood() {
fetch('/menu') // GET request to fetch menu items from the server
.then(response => response.json())
.then(data => {
menuItemsContainer.innerHTML = "";
data.forEach(item => {
const menuItemDiv = document.createElement('div');
menuItemDiv.classList.add('menu-item');
menuItemDiv.innerHTML = `
<h3>${item.Name}</h3>
<p><strong>Price:</strong> $${item.Price__c}</p>
<p><strong>Ingredients:</strong> ${item.Ingredients__c}</p>
<p><strong>Category:</strong> ${item.Category__c}</p>
<button class="order-btn" data-item="${item.Name}" onclick="takeOrder('${item.Name}')">Order</button>
`;
menuItemsContainer.appendChild(menuItemDiv);
});
speakMenuItems(data);
});
}
// Read out the menu items
function speakMenuItems(items) {
const utterance = new SpeechSynthesisUtterance("Here are the menu items:");
speechSynthesis.speak(utterance);
items.forEach(item => {
const itemUtterance = new SpeechSynthesisUtterance(`${item.Name}, Price: $${item.Price__c}, Ingredients: ${item.Ingredients__c}`);
speechSynthesis.speak(itemUtterance);
});
}
// Handle user order
function takeOrder(item) {
selectedItem = item;
const utterance = new SpeechSynthesisUtterance(`You selected ${item}. How many would you like?`);
speechSynthesis.speak(utterance);
status.textContent = `You selected ${item}. How many would you like?`;
startListeningForQuantity();
}
// Start listening for quantity
async function startListeningForQuantity() {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream, { mimeType: "audio/webm;codecs=opus" });
const audioChunks = [];
mediaRecorder.ondataavailable = (event) => audioChunks.push(event.data);
mediaRecorder.onstop = async () => {
const audioBlob = new Blob(audioChunks, { type: "audio/webm" });
const formData = new FormData();
formData.append("audio", audioBlob);
status.textContent = "Processing your quantity... Please wait.";
try {
const result = await fetch("/process-audio", { method: "POST", body: formData });
const data = await result.json();
quantity = parseInt(data.quantity);
status.textContent = `You want ${quantity} of ${selectedItem}. Please confirm your order.`;
confirmOrder();
} catch (error) {
status.textContent = "Sorry, I couldn’t understand that. Could you please repeat?";
isListening = false;
}
};
mediaRecorder.start();
setTimeout(() => mediaRecorder.stop(), 5000); // Stop recording after 5 seconds
}
// Confirm the order and send it to the backend
function confirmOrder() {
const orderDetails = {
item: selectedItem,
quantity: quantity
};
fetch('/order', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(orderDetails)
})
.then(response => response.json())
.then(data => {
status.textContent = `Order placed for ${quantity} of ${selectedItem}.`;
})
.catch(error => {
status.textContent = "Error placing order.";
});
}
</script>
</body>
</html>
|