Spaces:
Sleeping
Sleeping
Update static/script.js
Browse files- static/script.js +84 -216
static/script.js
CHANGED
@@ -31,7 +31,7 @@ function sendMessage() {
|
|
31 |
selectionBoxVisible = true;
|
32 |
handleResponse(message);
|
33 |
} else {
|
34 |
-
addMessage('bot', '
|
35 |
}
|
36 |
userInput.value = '';
|
37 |
updateSelectionBox();
|
@@ -42,7 +42,7 @@ function handleResponse(userInput) {
|
|
42 |
let botResponse = '';
|
43 |
|
44 |
if (conversation.length === 2) {
|
45 |
-
botResponse = `
|
46 |
displayOptions([
|
47 |
{ text: 'Vegetarian', class: 'green' },
|
48 |
{ text: 'Non-Vegetarian', class: 'red' },
|
@@ -50,11 +50,11 @@ function handleResponse(userInput) {
|
|
50 |
]);
|
51 |
addMessage('bot', botResponse);
|
52 |
} else if (lowerInput === 'vegetarian' || lowerInput === 'non-vegetarian' || lowerInput === 'both') {
|
53 |
-
botResponse = `
|
54 |
addMessage('bot', botResponse);
|
55 |
fetchMenuItems(lowerInput);
|
56 |
} else {
|
57 |
-
botResponse = `
|
58 |
addMessage('bot', botResponse);
|
59 |
fetchMenuItems(null, userInput);
|
60 |
}
|
@@ -73,13 +73,13 @@ function updateSelectionBox() {
|
|
73 |
selectionBox.className = 'selection-box';
|
74 |
|
75 |
const vegButton = document.createElement('button');
|
76 |
-
vegButton.textContent = '
|
77 |
vegButton.className = 'dietary-button green';
|
78 |
vegButton.onclick = () => fetchMenuItems('vegetarian');
|
79 |
selectionBox.appendChild(vegButton);
|
80 |
|
81 |
const nonVegButton = document.createElement('button');
|
82 |
-
nonVegButton.textContent = 'Non-
|
83 |
nonVegButton.className = 'dietary-button red';
|
84 |
nonVegButton.onclick = () => fetchMenuItems('non-vegetarian');
|
85 |
selectionBox.appendChild(nonVegButton);
|
@@ -91,7 +91,7 @@ function updateSelectionBox() {
|
|
91 |
selectionBox.appendChild(bothButton);
|
92 |
|
93 |
const label = document.createElement('span');
|
94 |
-
label.textContent = 'Selected
|
95 |
selectionBox.appendChild(label);
|
96 |
|
97 |
selectedItems.forEach((item, index) => {
|
@@ -109,11 +109,11 @@ function updateSelectionBox() {
|
|
109 |
itemContainer.appendChild(itemSpan);
|
110 |
|
111 |
const removeButton = document.createElement('button');
|
112 |
-
removeButton.textContent = '
|
113 |
removeButton.className = 'remove-button';
|
114 |
removeButton.onclick = () => {
|
115 |
selectedItems.splice(index, 1);
|
116 |
-
addMessage('bot', `Removed "${item.name}"
|
117 |
updateSelectionBox();
|
118 |
};
|
119 |
itemContainer.appendChild(removeButton);
|
@@ -123,7 +123,7 @@ function updateSelectionBox() {
|
|
123 |
|
124 |
const textInput = document.createElement('input');
|
125 |
textInput.type = 'text';
|
126 |
-
textInput.placeholder = 'Add
|
127 |
textInput.className = 'manual-input';
|
128 |
textInput.addEventListener('keypress', (e) => {
|
129 |
if (e.key === 'Enter' && textInput.value.trim()) {
|
@@ -139,26 +139,26 @@ function updateSelectionBox() {
|
|
139 |
quantityInput.type = 'number';
|
140 |
quantityInput.min = '1';
|
141 |
quantityInput.value = '1';
|
142 |
-
quantityInput.placeholder = '
|
143 |
quantityInput.className = 'quantity-input';
|
144 |
selectionBox.appendChild(quantityInput);
|
145 |
|
146 |
const submitButton = document.createElement('button');
|
147 |
-
submitButton.textContent = 'Submit
|
148 |
submitButton.className = 'submit-button';
|
149 |
submitButton.onclick = () => promptAndSubmit(quantityInput.value);
|
150 |
selectionBox.appendChild(submitButton);
|
151 |
|
152 |
const orderNameInput = document.createElement('input');
|
153 |
orderNameInput.type = 'text';
|
154 |
-
orderNameInput.placeholder = '
|
155 |
orderNameInput.className = 'order-name-input';
|
156 |
selectionBox.appendChild(orderNameInput);
|
157 |
}
|
158 |
|
159 |
chatMessages.appendChild(selectionBox);
|
160 |
chatMessages.scrollTop = chatMessages.scrollHeight;
|
161 |
-
console.log('Updated selection box
|
162 |
}
|
163 |
|
164 |
function fetchMenuItems(dietaryPreference, searchTerm = '') {
|
@@ -173,74 +173,21 @@ function fetchMenuItems(dietaryPreference, searchTerm = '') {
|
|
173 |
.then(response => response.json())
|
174 |
.then(data => {
|
175 |
if (data.error) {
|
176 |
-
addMessage('bot', `
|
177 |
} else if (data.menu_items.length > 0) {
|
178 |
-
addMessage('bot',
|
179 |
-
displayItemsList(data.menu_items
|
180 |
} else {
|
181 |
-
addMessage('bot', `No
|
182 |
}
|
183 |
console.log(`Fetched items for ${searchTerm || dietaryPreference}:`, data.menu_items);
|
184 |
})
|
185 |
.catch(error => {
|
186 |
-
addMessage('bot', `
|
187 |
setTimeout(() => fetchMenuItems(dietaryPreference, searchTerm), 2000);
|
188 |
});
|
189 |
}
|
190 |
|
191 |
-
function suggestItems(searchTerm) {
|
192 |
-
fetch('/suggest_items', {
|
193 |
-
method: 'POST',
|
194 |
-
headers: { 'Content-Type': 'application/json' },
|
195 |
-
body: JSON.stringify({ search_term: searchTerm })
|
196 |
-
})
|
197 |
-
.then(response => response.json())
|
198 |
-
.then(data => {
|
199 |
-
if (data.error) {
|
200 |
-
addMessage('bot', `Couldn’t find anything for "${searchTerm}": ${data.error}. Got another idea?`);
|
201 |
-
} else if (data.suggestions.length > 0) {
|
202 |
-
addMessage('bot', `Check out these suggestions for "${searchTerm}" from Ingredient_Object__c:`);
|
203 |
-
displayItemsList(data.suggestions, 'suggestionsList', false);
|
204 |
-
} else {
|
205 |
-
addMessage('bot', `No matches for "${searchTerm}" in Ingredient_Object__c. Try "chicken" or "paneer"?`);
|
206 |
-
}
|
207 |
-
console.log(`Suggestions for ${searchTerm}:`, data.suggestions);
|
208 |
-
})
|
209 |
-
.catch(error => {
|
210 |
-
addMessage('bot', `Error fetching suggestions: ${error.message}. Retrying...`);
|
211 |
-
setTimeout(() => suggestItems(searchTerm), 2000);
|
212 |
-
});
|
213 |
-
}
|
214 |
-
|
215 |
-
function fetchItemDetails(itemName) {
|
216 |
-
fetch('/get_item_details', {
|
217 |
-
method: 'POST',
|
218 |
-
headers: { 'Content-Type': 'application/json' },
|
219 |
-
body: JSON.stringify({ item_name: itemName })
|
220 |
-
})
|
221 |
-
.then(response => response.json())
|
222 |
-
.then(data => {
|
223 |
-
if (data.error) {
|
224 |
-
addMessage('bot', `Couldn’t find "${itemName}" in Ingredient_Object__c. Add it manually in the box below!`);
|
225 |
-
updateSelectionBox();
|
226 |
-
} else {
|
227 |
-
const details = data.item_details;
|
228 |
-
if (selectedItems.some(item => item.name === details.name)) {
|
229 |
-
addMessage('bot', `"${details.name}" is already in your selection!`);
|
230 |
-
} else {
|
231 |
-
selectedItems.push({ ...details, quantity: 1 });
|
232 |
-
addMessage('bot', `Added "${itemName}" to your selection! Check the box below.`);
|
233 |
-
updateSelectionBox();
|
234 |
-
}
|
235 |
-
}
|
236 |
-
})
|
237 |
-
.catch(error => {
|
238 |
-
addMessage('bot', `Trouble fetching "${itemName}": ${error.message}. Add it manually or I’ll retry...`);
|
239 |
-
updateSelectionBox();
|
240 |
-
setTimeout(() => fetchItemDetails(itemName), 2000);
|
241 |
-
});
|
242 |
-
}
|
243 |
-
|
244 |
function fetchSectorItemDetails(itemName) {
|
245 |
fetch('/get_sector_item_details', {
|
246 |
method: 'POST',
|
@@ -250,178 +197,107 @@ function fetchSectorItemDetails(itemName) {
|
|
250 |
.then(response => response.json())
|
251 |
.then(data => {
|
252 |
if (data.error) {
|
253 |
-
addMessage('bot', `
|
254 |
} else {
|
255 |
const details = data.item_details;
|
256 |
if (selectedItems.some(item => item.name === details.name)) {
|
257 |
-
addMessage('bot', `"${details.name}"
|
258 |
} else {
|
259 |
selectedItems.push({ ...details, quantity: 1 });
|
260 |
-
addMessage('bot', `Added "${details.name}"
|
261 |
updateSelectionBox();
|
262 |
}
|
263 |
}
|
264 |
})
|
265 |
.catch(error => {
|
266 |
-
addMessage('bot', `Error
|
267 |
setTimeout(() => fetchSectorItemDetails(itemName), 2000);
|
268 |
});
|
269 |
}
|
270 |
|
271 |
-
function
|
272 |
-
|
273 |
-
if (
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
const img = document.createElement('img');
|
282 |
-
img.src = item.image_url || 'https://via.placeholder.com/100';
|
283 |
-
img.alt = item.name;
|
284 |
-
img.className = 'popup-image';
|
285 |
-
content.appendChild(img);
|
286 |
-
|
287 |
-
const title = document.createElement('h3');
|
288 |
-
title.textContent = item.name;
|
289 |
-
content.appendChild(title);
|
290 |
-
|
291 |
-
const desc = document.createElement('p');
|
292 |
-
desc.textContent = item.description || 'No description available';
|
293 |
-
content.appendChild(desc);
|
294 |
-
|
295 |
-
if (item.source === 'Menu_Item__c') {
|
296 |
-
const fields = [
|
297 |
-
{ label: 'Category', value: item.category },
|
298 |
-
{ label: 'Veg/Non-Veg', value: item.veg_nonveg },
|
299 |
-
{ label: 'Ingredients', value: item.ingredients },
|
300 |
-
{ label: 'Nutritional Info', value: item.nutritional_info },
|
301 |
-
{ label: 'Price', value: item.price ? `$${item.price.toFixed(2)}` : 'N/A' },
|
302 |
-
{ label: 'Sector', value: item.sector },
|
303 |
-
{ label: 'Spice Levels', value: item.spice_levels },
|
304 |
-
{ label: 'Dynamic Dish', value: item.dynamic_dish ? 'Yes' : 'No' }
|
305 |
-
];
|
306 |
-
fields.forEach(field => {
|
307 |
-
if (field.value) {
|
308 |
-
const p = document.createElement('p');
|
309 |
-
p.className = 'menu-item-field';
|
310 |
-
p.innerHTML = `<strong>${field.label}:</strong> ${field.value}`;
|
311 |
-
content.appendChild(p);
|
312 |
-
}
|
313 |
-
});
|
314 |
} else {
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
}
|
319 |
-
|
320 |
-
const buttonContainer = document.createElement('div');
|
321 |
-
buttonContainer.className = 'button-container';
|
322 |
-
|
323 |
-
const addButton = document.createElement('button');
|
324 |
-
addButton.textContent = 'Add';
|
325 |
-
addButton.className = 'popup-add-button';
|
326 |
-
addButton.onclick = () => {
|
327 |
-
const selectedItem = {
|
328 |
-
name: item.name,
|
329 |
-
image_url: item.image_url || '',
|
330 |
-
category: item.category || 'Not specified',
|
331 |
-
description: item.description || 'No description available',
|
332 |
-
source: item.source,
|
333 |
-
quantity: 1
|
334 |
-
};
|
335 |
-
if (item.source === 'Menu_Item__c') {
|
336 |
-
selectedItem.ingredients = item.ingredients;
|
337 |
-
selectedItem.nutritional_info = item.nutritional_info;
|
338 |
-
selectedItem.price = item.price;
|
339 |
-
selectedItem.sector = item.sector;
|
340 |
-
selectedItem.spice_levels = item.spice_levels;
|
341 |
-
selectedItem.veg_nonveg = item.veg_nonveg;
|
342 |
-
selectedItem.dynamic_dish = item.dynamic_dish;
|
343 |
-
}
|
344 |
-
if (selectedItems.some(existing => existing.name === selectedItem.name)) {
|
345 |
-
addMessage('-known', `"${selectedItem.name}" is already in your selection!`);
|
346 |
-
} else {
|
347 |
-
selectedItems.push(selectedItem);
|
348 |
-
addMessage('bot', `Added "${selectedItem.name}" to your selection! Check the box below.`);
|
349 |
-
updateSelectionBox();
|
350 |
-
}
|
351 |
-
popup.remove();
|
352 |
-
};
|
353 |
-
buttonContainer.appendChild(addButton);
|
354 |
-
|
355 |
-
const closeButton = document.createElement('button');
|
356 |
-
closeButton.textContent = 'Close';
|
357 |
-
closeButton.className = 'popup-close-button';
|
358 |
-
closeButton.onclick = () => popup.remove();
|
359 |
-
buttonContainer.appendChild(closeButton);
|
360 |
-
|
361 |
-
content.appendChild(buttonContainer);
|
362 |
-
popup.appendChild(content);
|
363 |
-
document.body.appendChild(popup);
|
364 |
}
|
365 |
|
366 |
-
function displayItemsList(items
|
367 |
-
const
|
368 |
-
if (!
|
369 |
-
console.error(
|
370 |
-
addMessage('bot', '
|
371 |
return;
|
372 |
}
|
373 |
-
|
374 |
-
|
|
|
375 |
|
376 |
items.forEach(item => {
|
377 |
const itemDiv = document.createElement('div');
|
378 |
-
itemDiv.className = '
|
|
|
379 |
|
380 |
const img = document.createElement('img');
|
381 |
img.src = item.image_url || 'https://via.placeholder.com/60';
|
382 |
img.alt = item.name;
|
383 |
-
img.className = '
|
384 |
itemDiv.appendChild(img);
|
385 |
|
386 |
const contentDiv = document.createElement('div');
|
387 |
-
contentDiv.className = '
|
388 |
|
389 |
const nameDiv = document.createElement('div');
|
390 |
nameDiv.textContent = item.name;
|
391 |
-
nameDiv.className = '
|
392 |
contentDiv.appendChild(nameDiv);
|
393 |
|
394 |
-
if (item.source === 'Menu_Item__c'
|
395 |
const fields = [
|
396 |
{ label: 'Price', value: item.price ? `$${item.price.toFixed(2)}` : 'N/A' },
|
397 |
{ label: 'Veg/Non-Veg', value: item.veg_nonveg },
|
398 |
-
{ label: 'Spice
|
399 |
{ label: 'Category', value: item.category },
|
400 |
{ label: 'Ingredients', value: item.ingredients },
|
401 |
-
{ label: '
|
402 |
{ label: 'Sector', value: item.sector },
|
403 |
-
{ label: 'Dynamic
|
404 |
];
|
405 |
fields.forEach(field => {
|
406 |
if (field.value) {
|
407 |
const p = document.createElement('p');
|
408 |
-
p.className = '
|
409 |
p.innerHTML = `<strong>${field.label}:</strong> ${field.value}`;
|
410 |
contentDiv.appendChild(p);
|
411 |
}
|
412 |
});
|
413 |
-
} else if (item.source === 'Sector_Detail__c' && isDetailed) {
|
414 |
-
const desc = document.createElement('p');
|
415 |
-
desc.className = 'menu-item-field';
|
416 |
-
desc.innerHTML = `<strong>Description:</strong> ${item.description}`;
|
417 |
-
contentDiv.appendChild(desc);
|
418 |
}
|
419 |
|
420 |
itemDiv.appendChild(contentDiv);
|
421 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
422 |
const addButton = document.createElement('button');
|
423 |
addButton.textContent = 'Add';
|
424 |
-
addButton.className = '
|
425 |
addButton.onclick = () => {
|
426 |
const selectedItem = {
|
427 |
name: item.name,
|
@@ -441,35 +317,31 @@ function displayItemsList(items, containerId, isDetailed = false) {
|
|
441 |
selectedItem.dynamic_dish = item.dynamic_dish;
|
442 |
}
|
443 |
if (selectedItems.some(existing => existing.name === selectedItem.name)) {
|
444 |
-
addMessage('bot', `"${selectedItem.name}"
|
445 |
} else {
|
446 |
selectedItems.push(selectedItem);
|
447 |
-
addMessage('bot', `Added "${selectedItem.name}"
|
448 |
updateSelectionBox();
|
449 |
}
|
450 |
};
|
451 |
-
|
452 |
-
|
453 |
-
if (item.source === 'Sector_Detail__c' && isDetailed) {
|
454 |
-
const showDescButton = document.createElement('button');
|
455 |
-
showDescButton.textContent = 'Show Details';
|
456 |
-
showDescButton.className = 'show-desc-button';
|
457 |
-
showDescButton.onclick = () => showDescriptionPopup(item);
|
458 |
-
itemDiv.appendChild(showDescButton);
|
459 |
-
}
|
460 |
|
461 |
-
|
|
|
462 |
});
|
|
|
|
|
|
|
463 |
}
|
464 |
|
465 |
function displayOptions(options) {
|
466 |
const chatMessages = document.getElementById('chatMessages');
|
467 |
if (!chatMessages) {
|
468 |
-
console.error('Chat messages container not found
|
469 |
return;
|
470 |
}
|
471 |
const optionsDiv = document.createElement('div');
|
472 |
-
optionsDiv.
|
473 |
|
474 |
options.forEach(opt => {
|
475 |
const button = document.createElement('button');
|
@@ -486,11 +358,9 @@ function displayOptions(options) {
|
|
486 |
});
|
487 |
|
488 |
const backButton = document.createElement('button');
|
489 |
-
backButton.textContent = '
|
490 |
backButton.className = 'option-button';
|
491 |
-
backButton.style.marginTop = '10px';
|
492 |
backButton.onclick = () => resetConversation();
|
493 |
-
optionsDiv.appendChild(document.createElement('br'));
|
494 |
optionsDiv.appendChild(backButton);
|
495 |
|
496 |
chatMessages.appendChild(optionsDiv);
|
@@ -499,16 +369,16 @@ function displayOptions(options) {
|
|
499 |
function promptAndSubmit(quantity) {
|
500 |
const orderNameInput = document.querySelector('.order-name-input');
|
501 |
const customOrderName = orderNameInput ? orderNameInput.value.trim() : '';
|
502 |
-
if (confirm(`Submit ${selectedItems.length} items
|
503 |
submitToSalesforce(customOrderName, quantity);
|
504 |
} else {
|
505 |
-
addMessage('bot', '
|
506 |
}
|
507 |
}
|
508 |
|
509 |
function submitToSalesforce(customOrderName, quantity) {
|
510 |
if (selectedItems.length === 0) {
|
511 |
-
addMessage('bot', 'No items
|
512 |
return;
|
513 |
}
|
514 |
|
@@ -528,15 +398,15 @@ function submitToSalesforce(customOrderName, quantity) {
|
|
528 |
.then(response => response.json())
|
529 |
.then(data => {
|
530 |
if (data.error) {
|
531 |
-
addMessage('bot', `
|
532 |
} else {
|
533 |
-
addMessage('bot',
|
534 |
selectedItems = [];
|
535 |
updateSelectionBox();
|
536 |
}
|
537 |
})
|
538 |
.catch(error => {
|
539 |
-
addMessage('bot', `
|
540 |
setTimeout(() => submitToSalesforce(customOrderName, quantity), 2000);
|
541 |
});
|
542 |
}
|
@@ -546,7 +416,7 @@ function resetConversation() {
|
|
546 |
conversation = [
|
547 |
{ role: 'bot', message: `Hello! I’m Chef Bot, your culinary assistant! What’s your name?` },
|
548 |
{ role: 'user', message: userName },
|
549 |
-
{ role: 'bot', message: `
|
550 |
];
|
551 |
selectedItems = [];
|
552 |
selectionBoxVisible = true;
|
@@ -558,8 +428,6 @@ function resetConversation() {
|
|
558 |
{ text: 'Non-Vegetarian', class: 'red' },
|
559 |
{ text: 'Both', class: 'gray' }
|
560 |
]);
|
561 |
-
document.getElementById('suggestionsList').innerHTML = '';
|
562 |
-
document.getElementById('menuItemsList').innerHTML = '';
|
563 |
updateSelectionBox();
|
564 |
}
|
565 |
|
@@ -567,4 +435,4 @@ document.getElementById('userInput').addEventListener('keypress', (e) => {
|
|
567 |
if (e.key === 'Enter') sendMessage();
|
568 |
});
|
569 |
|
570 |
-
console.log('Chef Bot script loaded
|
|
|
31 |
selectionBoxVisible = true;
|
32 |
handleResponse(message);
|
33 |
} else {
|
34 |
+
addMessage('bot', 'Please type a dish or pick a preference! 😄');
|
35 |
}
|
36 |
userInput.value = '';
|
37 |
updateSelectionBox();
|
|
|
42 |
let botResponse = '';
|
43 |
|
44 |
if (conversation.length === 2) {
|
45 |
+
botResponse = `Hi ${userInput}! 🍳 Search for a dish or choose a preference below!`;
|
46 |
displayOptions([
|
47 |
{ text: 'Vegetarian', class: 'green' },
|
48 |
{ text: 'Non-Vegetarian', class: 'red' },
|
|
|
50 |
]);
|
51 |
addMessage('bot', botResponse);
|
52 |
} else if (lowerInput === 'vegetarian' || lowerInput === 'non-vegetarian' || lowerInput === 'both') {
|
53 |
+
botResponse = `Fetching ${lowerInput} dishes...`;
|
54 |
addMessage('bot', botResponse);
|
55 |
fetchMenuItems(lowerInput);
|
56 |
} else {
|
57 |
+
botResponse = `Looking for "${userInput}"...`;
|
58 |
addMessage('bot', botResponse);
|
59 |
fetchMenuItems(null, userInput);
|
60 |
}
|
|
|
73 |
selectionBox.className = 'selection-box';
|
74 |
|
75 |
const vegButton = document.createElement('button');
|
76 |
+
vegButton.textContent = 'Veg';
|
77 |
vegButton.className = 'dietary-button green';
|
78 |
vegButton.onclick = () => fetchMenuItems('vegetarian');
|
79 |
selectionBox.appendChild(vegButton);
|
80 |
|
81 |
const nonVegButton = document.createElement('button');
|
82 |
+
nonVegButton.textContent = 'Non-Veg';
|
83 |
nonVegButton.className = 'dietary-button red';
|
84 |
nonVegButton.onclick = () => fetchMenuItems('non-vegetarian');
|
85 |
selectionBox.appendChild(nonVegButton);
|
|
|
91 |
selectionBox.appendChild(bothButton);
|
92 |
|
93 |
const label = document.createElement('span');
|
94 |
+
label.textContent = 'Selected:';
|
95 |
selectionBox.appendChild(label);
|
96 |
|
97 |
selectedItems.forEach((item, index) => {
|
|
|
109 |
itemContainer.appendChild(itemSpan);
|
110 |
|
111 |
const removeButton = document.createElement('button');
|
112 |
+
removeButton.textContent = 'X';
|
113 |
removeButton.className = 'remove-button';
|
114 |
removeButton.onclick = () => {
|
115 |
selectedItems.splice(index, 1);
|
116 |
+
addMessage('bot', `Removed "${item.name}".`);
|
117 |
updateSelectionBox();
|
118 |
};
|
119 |
itemContainer.appendChild(removeButton);
|
|
|
123 |
|
124 |
const textInput = document.createElement('input');
|
125 |
textInput.type = 'text';
|
126 |
+
textInput.placeholder = 'Add item...';
|
127 |
textInput.className = 'manual-input';
|
128 |
textInput.addEventListener('keypress', (e) => {
|
129 |
if (e.key === 'Enter' && textInput.value.trim()) {
|
|
|
139 |
quantityInput.type = 'number';
|
140 |
quantityInput.min = '1';
|
141 |
quantityInput.value = '1';
|
142 |
+
quantityInput.placeholder = 'Qty';
|
143 |
quantityInput.className = 'quantity-input';
|
144 |
selectionBox.appendChild(quantityInput);
|
145 |
|
146 |
const submitButton = document.createElement('button');
|
147 |
+
submitButton.textContent = 'Submit';
|
148 |
submitButton.className = 'submit-button';
|
149 |
submitButton.onclick = () => promptAndSubmit(quantityInput.value);
|
150 |
selectionBox.appendChild(submitButton);
|
151 |
|
152 |
const orderNameInput = document.createElement('input');
|
153 |
orderNameInput.type = 'text';
|
154 |
+
orderNameInput.placeholder = 'Order Name';
|
155 |
orderNameInput.className = 'order-name-input';
|
156 |
selectionBox.appendChild(orderNameInput);
|
157 |
}
|
158 |
|
159 |
chatMessages.appendChild(selectionBox);
|
160 |
chatMessages.scrollTop = chatMessages.scrollHeight;
|
161 |
+
console.log('Updated selection box:', selectedItems.map(item => ({ name: item.name, category: item.category })));
|
162 |
}
|
163 |
|
164 |
function fetchMenuItems(dietaryPreference, searchTerm = '') {
|
|
|
173 |
.then(response => response.json())
|
174 |
.then(data => {
|
175 |
if (data.error) {
|
176 |
+
addMessage('bot', `Error: ${data.error}. Try again!`);
|
177 |
} else if (data.menu_items.length > 0) {
|
178 |
+
addMessage('bot', `--- Found ${data.menu_items.length} item${data.menu_items.length > 1 ? 's' : ''} ---`);
|
179 |
+
displayItemsList(data.menu_items);
|
180 |
} else {
|
181 |
+
addMessage('bot', `No matches for "${searchTerm || dietaryPreference}". Try "paneer"!`);
|
182 |
}
|
183 |
console.log(`Fetched items for ${searchTerm || dietaryPreference}:`, data.menu_items);
|
184 |
})
|
185 |
.catch(error => {
|
186 |
+
addMessage('bot', `Connection issue: ${error.message}. Retrying...`);
|
187 |
setTimeout(() => fetchMenuItems(dietaryPreference, searchTerm), 2000);
|
188 |
});
|
189 |
}
|
190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
function fetchSectorItemDetails(itemName) {
|
192 |
fetch('/get_sector_item_details', {
|
193 |
method: 'POST',
|
|
|
197 |
.then(response => response.json())
|
198 |
.then(data => {
|
199 |
if (data.error) {
|
200 |
+
addMessage('bot', `No "${itemName}" found. Try another!`);
|
201 |
} else {
|
202 |
const details = data.item_details;
|
203 |
if (selectedItems.some(item => item.name === details.name)) {
|
204 |
+
addMessage('bot', `"${details.name}" already selected!`);
|
205 |
} else {
|
206 |
selectedItems.push({ ...details, quantity: 1 });
|
207 |
+
addMessage('bot', `Added "${details.name}"!`);
|
208 |
updateSelectionBox();
|
209 |
}
|
210 |
}
|
211 |
})
|
212 |
.catch(error => {
|
213 |
+
addMessage('bot', `Error for "${itemName}". Retrying...`);
|
214 |
setTimeout(() => fetchSectorItemDetails(itemName), 2000);
|
215 |
});
|
216 |
}
|
217 |
|
218 |
+
function toggleDescription(itemDiv, description, itemName) {
|
219 |
+
let descElement = itemDiv.querySelector('.item-description');
|
220 |
+
if (!descElement) {
|
221 |
+
descElement = document.createElement('p');
|
222 |
+
descElement.className = 'item-description';
|
223 |
+
descElement.textContent = description;
|
224 |
+
itemDiv.querySelector('.item-content').appendChild(descElement);
|
225 |
+
itemDiv.dataset.hidden = 'false';
|
226 |
+
console.log(`Showed description for ${itemName}`);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
} else {
|
228 |
+
descElement.remove();
|
229 |
+
itemDiv.dataset.hidden = 'true';
|
230 |
+
console.log(`Hid description for ${itemName}`);
|
231 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
}
|
233 |
|
234 |
+
function displayItemsList(items) {
|
235 |
+
const chatMessages = document.getElementById('chatMessages');
|
236 |
+
if (!chatMessages) {
|
237 |
+
console.error('Chat messages container not found!');
|
238 |
+
addMessage('bot', 'Display issue. Try again?');
|
239 |
return;
|
240 |
}
|
241 |
+
|
242 |
+
const itemsGrid = document.createElement('div');
|
243 |
+
itemsGrid.className = 'items-grid';
|
244 |
|
245 |
items.forEach(item => {
|
246 |
const itemDiv = document.createElement('div');
|
247 |
+
itemDiv.className = 'item-card';
|
248 |
+
itemDiv.dataset.hidden = item.source === 'Sector_Detail__c' ? 'true' : 'false';
|
249 |
|
250 |
const img = document.createElement('img');
|
251 |
img.src = item.image_url || 'https://via.placeholder.com/60';
|
252 |
img.alt = item.name;
|
253 |
+
img.className = 'item-image';
|
254 |
itemDiv.appendChild(img);
|
255 |
|
256 |
const contentDiv = document.createElement('div');
|
257 |
+
contentDiv.className = 'item-content';
|
258 |
|
259 |
const nameDiv = document.createElement('div');
|
260 |
nameDiv.textContent = item.name;
|
261 |
+
nameDiv.className = 'item-name';
|
262 |
contentDiv.appendChild(nameDiv);
|
263 |
|
264 |
+
if (item.source === 'Menu_Item__c') {
|
265 |
const fields = [
|
266 |
{ label: 'Price', value: item.price ? `$${item.price.toFixed(2)}` : 'N/A' },
|
267 |
{ label: 'Veg/Non-Veg', value: item.veg_nonveg },
|
268 |
+
{ label: 'Spice', value: item.spice_levels },
|
269 |
{ label: 'Category', value: item.category },
|
270 |
{ label: 'Ingredients', value: item.ingredients },
|
271 |
+
{ label: 'Nutrition', value: item.nutritional_info },
|
272 |
{ label: 'Sector', value: item.sector },
|
273 |
+
{ label: 'Dynamic', value: item.dynamic_dish ? 'Yes' : 'No' }
|
274 |
];
|
275 |
fields.forEach(field => {
|
276 |
if (field.value) {
|
277 |
const p = document.createElement('p');
|
278 |
+
p.className = 'item-field';
|
279 |
p.innerHTML = `<strong>${field.label}:</strong> ${field.value}`;
|
280 |
contentDiv.appendChild(p);
|
281 |
}
|
282 |
});
|
|
|
|
|
|
|
|
|
|
|
283 |
}
|
284 |
|
285 |
itemDiv.appendChild(contentDiv);
|
286 |
|
287 |
+
const buttonContainer = document.createElement('div');
|
288 |
+
buttonContainer.className = 'button-container';
|
289 |
+
|
290 |
+
if (item.source === 'Sector_Detail__c') {
|
291 |
+
const showButton = document.createElement('button');
|
292 |
+
showButton.textContent = 'Show';
|
293 |
+
showButton.className = 'show-button';
|
294 |
+
showButton.onclick = () => toggleDescription(itemDiv, item.description, item.name);
|
295 |
+
buttonContainer.appendChild(showButton);
|
296 |
+
}
|
297 |
+
|
298 |
const addButton = document.createElement('button');
|
299 |
addButton.textContent = 'Add';
|
300 |
+
addButton.className = 'add-button';
|
301 |
addButton.onclick = () => {
|
302 |
const selectedItem = {
|
303 |
name: item.name,
|
|
|
317 |
selectedItem.dynamic_dish = item.dynamic_dish;
|
318 |
}
|
319 |
if (selectedItems.some(existing => existing.name === selectedItem.name)) {
|
320 |
+
addMessage('bot', `"${selectedItem.name}" already selected!`);
|
321 |
} else {
|
322 |
selectedItems.push(selectedItem);
|
323 |
+
addMessage('bot', `Added "${selectedItem.name}"!`);
|
324 |
updateSelectionBox();
|
325 |
}
|
326 |
};
|
327 |
+
buttonContainer.appendChild(addButton);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
|
329 |
+
itemDiv.appendChild(buttonContainer);
|
330 |
+
itemsGrid.appendChild(itemDiv);
|
331 |
});
|
332 |
+
|
333 |
+
chatMessages.appendChild(itemsGrid);
|
334 |
+
chatMessages.scrollTop = chatMessages.scrollHeight;
|
335 |
}
|
336 |
|
337 |
function displayOptions(options) {
|
338 |
const chatMessages = document.getElementById('chatMessages');
|
339 |
if (!chatMessages) {
|
340 |
+
console.error('Chat messages container not found!');
|
341 |
return;
|
342 |
}
|
343 |
const optionsDiv = document.createElement('div');
|
344 |
+
optionsDiv.className = 'options-container';
|
345 |
|
346 |
options.forEach(opt => {
|
347 |
const button = document.createElement('button');
|
|
|
358 |
});
|
359 |
|
360 |
const backButton = document.createElement('button');
|
361 |
+
backButton.textContent = 'Back';
|
362 |
backButton.className = 'option-button';
|
|
|
363 |
backButton.onclick = () => resetConversation();
|
|
|
364 |
optionsDiv.appendChild(backButton);
|
365 |
|
366 |
chatMessages.appendChild(optionsDiv);
|
|
|
369 |
function promptAndSubmit(quantity) {
|
370 |
const orderNameInput = document.querySelector('.order-name-input');
|
371 |
const customOrderName = orderNameInput ? orderNameInput.value.trim() : '';
|
372 |
+
if (confirm(`Submit ${selectedItems.length} items (Qty: ${quantity})?`)) {
|
373 |
submitToSalesforce(customOrderName, quantity);
|
374 |
} else {
|
375 |
+
addMessage('bot', 'Cancelled. Add more items?');
|
376 |
}
|
377 |
}
|
378 |
|
379 |
function submitToSalesforce(customOrderName, quantity) {
|
380 |
if (selectedItems.length === 0) {
|
381 |
+
addMessage('bot', 'No items selected! Add some dishes! 😊');
|
382 |
return;
|
383 |
}
|
384 |
|
|
|
398 |
.then(response => response.json())
|
399 |
.then(data => {
|
400 |
if (data.error) {
|
401 |
+
addMessage('bot', `Submission failed: ${data.error}. Try again?`);
|
402 |
} else {
|
403 |
+
addMessage('bot', `Submitted ${data.ingredient_name}! What's next?`);
|
404 |
selectedItems = [];
|
405 |
updateSelectionBox();
|
406 |
}
|
407 |
})
|
408 |
.catch(error => {
|
409 |
+
addMessage('bot', `Submission error: ${error.message}. Retrying...`);
|
410 |
setTimeout(() => submitToSalesforce(customOrderName, quantity), 2000);
|
411 |
});
|
412 |
}
|
|
|
416 |
conversation = [
|
417 |
{ role: 'bot', message: `Hello! I’m Chef Bot, your culinary assistant! What’s your name?` },
|
418 |
{ role: 'user', message: userName },
|
419 |
+
{ role: 'bot', message: `Hi ${userName}! 🍳 Search for a dish or choose a preference below!` }
|
420 |
];
|
421 |
selectedItems = [];
|
422 |
selectionBoxVisible = true;
|
|
|
428 |
{ text: 'Non-Vegetarian', class: 'red' },
|
429 |
{ text: 'Both', class: 'gray' }
|
430 |
]);
|
|
|
|
|
431 |
updateSelectionBox();
|
432 |
}
|
433 |
|
|
|
435 |
if (e.key === 'Enter') sendMessage();
|
436 |
});
|
437 |
|
438 |
+
console.log('Chef Bot script loaded!');
|